Index: doc/bibliography/pl.bib
===================================================================
--- doc/bibliography/pl.bib	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ doc/bibliography/pl.bib	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -4108,5 +4108,5 @@
 }
 
-@article{Buhr22,
+@article{Buhr23,
     contributer	= {pabuhr@plg},
     author	= {Peter A. Buhr and Colby A. Parsons and Thierry Delisle and He Nan Li},
@@ -4114,6 +4114,9 @@
     journal	= spe,
     year	= 2023,
-    month	= sep,
-    note	= {\url{https://onlinelibrary.wiley.com/doi/pdf/10.1002/spe.3262}}
+    month	= dec,
+    volume	= 53,
+    number	= 12,
+    pages	= {2463-2500},
+    note	= {\url{https://onlinelibrary.wiley.com/doi/10.1002/spe.3262},
 }
 
@@ -4133,8 +4136,8 @@
     journal	= spe,
     year	= 1983,
+    month	= jul,
     volume	= 13,
     number	= 7,
     pages	= {577-596},
-    month	= jul
 }
 
Index: c/proposals/enum.md
===================================================================
--- doc/proposals/enum.md	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,70 +1,0 @@
-# Plan: CFA Typed Enum 
-## Introduction
-CFA allows users to define enum with any type, and an enum's value is a subset of its supertype. The basic syntax of defining a typed enum is the follows:
-
-<div align="center">
-<i>enum(Typename) EnumName<sub>opt</sub> = { enumerator-list }</i>
-</div> or
-, where <i>enumerator-list</i> is a list of <i>identifier</i> or <i>identifier = const-expression</i>.  
-<div>
-
-</div>
-
-## CFA Typed Enum vs C Enum vs C++ Enum
-In C, an enum variable declaration is isomorphic to an integer declaration. For example,  
-<div align="center">
-<i>enum EnumType VariableName = EnumValue;</i>
-</div>
-is equivalent to
-<div align="center">
-<i>int VariableName = EnumValue;</i>
-</div>
-For backward capatability, we perserve this behaviour in CFA. This is different from an C++ interpretation. C++ disallow an assignment to an enum variable with a value from the base type without an explicit cast. However, if a user defines an enum E using the typed syntax:
-<div align="center">
-<i>enum E(int) = EnumValue;</i>
-</div>
-Now <i>E</i> is a proper subset of <i>int</i> type. The compiler will stop you from assignment an integer value of a variable with type E, as in C++.</p>
-Since C++11, C++ supports enum definition with an enum base.
-<div align="center">
-<i>enum EnumName : enum-base = { enumerator-list };</i>
-</div>
-An enum base is a sequence of basic integral type specifier.
-<div align="center">
-<i>
-enum E: char {A='a'};<br/>
-E e = A; <br/>
-cout << e << end;
-</i>
-</div>
-Will print a character 'a' to the output instead of 97.</br>
-CFA extends this idea to allows a typed enum to have an non-intergral or non-basic type. You can create an enum with a base type floating number, pointer, tuple, structure, function pointer, another enum, and more.  
-
-## Implementation / Todo
-### 0. Grammar  
-Enumerator_value_opt:  
-	// empty  
-	// | '=' constant_expression  
-	// 	{ $$ = $2; }  
-	| simple_assignment_operator initializer					// FIX ME: enum only deals with constant_expression
-	;  
-Discussion: FIX ME item.  
-### 1. Integral Type:
-$\forall$ enum_expression :  <i>enum($T$) { enumerator_list comma<sub>opt</sub> }</i>,  
-where $T \in IntegralTypes.$  
-For $enumerator\_list \rightarrow$<sub>derive</sub> $identifier = constant\_expression$:   
-&emsp;$Code(enumerator\_list) = Code(const\ T \ identifier = constant\_expression)$  
-For $enumerator\_list \rightarrow$<sub>derive</sub> $identifier_k$ :   
-&emsp;$Code(enumerator\_list) = Code(const\ T \ identifier_k = identifier_{k-1}+1)(k>0)$  
-&emsp;$Code(enumerator\_list) = Code(const\ T \ identifier_k = 0)(k=0)$  
-  
-During the code compilation, probably during the <i>static type checking</i> we save all the enum element <b>Names</b>. A compiler throws error if an assignment to an enum variable with a expression that is not an enum name.  
-$enum\ T(int) \{A =\ 'a'\}$  
-$T\ Name =\ 'a' $// Error: Cannot assign a variable of type 'T' with a value of type 'char'.  
-It behaves the same as C++ and many other languages.
-
-
-### 2. Non-Integral Type  
-Syntax: 
-$enumerator\_list \rightarrow$<sub>derive</sub> $identifier = constant\_expression$
-
-
Index: doc/proposals/enum.tex
===================================================================
--- doc/proposals/enum.tex	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ doc/proposals/enum.tex	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -1,313 +1,592 @@
-%%
-%% This is file `sample-manuscript.tex',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% samples.dtx  (with options: `manuscript')
-%% 
-%% IMPORTANT NOTICE:
-%% 
-%% For the copyright see the source file.
-%% 
-%% Any modified versions of this file must be renamed
-%% with new filenames distinct from sample-manuscript.tex.
-%% 
-%% For distribution of the original source see the terms
-%% for copying and modification in the file samples.dtx.
-%% 
-%% This generated file may be distributed as long as the
-%% original source files, as listed above, are part of the
-%% same distribution. (The sources need not necessarily be
-%% in the same archive or directory.)
-%%
-%% Commands for TeXCount
-%TC:macro \cite [option:text,text]
-%TC:macro \citep [option:text,text]
-%TC:macro \citet [option:text,text]
-%TC:envir table 0 1
-%TC:envir table* 0 1
-%TC:envir tabular [ignore] word
-%TC:envir displaymath 0 word
-%TC:envir math 0 word
-%TC:envir comment 0 0
-%%
-%%
-%% The first command in your LaTeX source must be the \documentclass command.
-\documentclass[manuscript,screen,review]{acmart}
+\documentclass[12pt]{article}
+\usepackage{fullpage,times}
+\usepackage{pslatex}			% reduce size of san serif font
 \usepackage{xcolor}
 \usepackage{listings}
-\usepackage[ligature, inference]{semantic}
-\usepackage{array}
-
-\definecolor{mGreen}{rgb}{0,0.6,0}
-\definecolor{mGray}{rgb}{0.5,0.5,0.5}
-\definecolor{mPurple}{rgb}{0.58,0,0.82}
-\definecolor{backgroundColour}{rgb}{0.95,0.95,0.92}
+%\usepackage{array}
+\usepackage{graphics}
+\usepackage{xspace}
+
+\makeatletter
+\renewcommand\section{\@startsection{section}{1}{\z@}{-3.0ex \@plus -1ex \@minus -.2ex}{1.5ex \@plus .2ex}{\normalfont\large\bfseries}}
+\renewcommand\subsection{\@startsection{subsection}{2}{\z@}{-2.75ex \@plus -1ex \@minus -.2ex}{1.25ex \@plus .2ex}{\normalfont\normalsize\bfseries}}
+\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}{-2.5ex \@plus -1ex \@minus -.2ex}{1.0ex \@plus .2ex}{\normalfont\normalsize\bfseries}}
+\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}{-2.0ex \@plus -1ex \@minus -.2ex}{-1em}{\normalfont\normalsize\bfseries}}
+\renewcommand\subparagraph{\@startsection{subparagraph}{4}{\z@}{-1.5ex \@plus -1ex \@minus -.2ex}{-1em}{\normalfont\normalsize\bfseries\itshape}}
+\makeatother
+
+\usepackage[ignoredisplayed]{enumitem}	% do not affect trivlist
+\setlist{labelsep=1ex}% global
+\setlist[itemize]{topsep=0.5ex,parsep=0.25ex,itemsep=0.25ex,listparindent=\parindent,leftmargin=\parindent}% global
+\setlist[itemize,1]{label=\textbullet}% local
+%\renewcommand{\labelitemi}{{\raisebox{0.25ex}{\footnotesize$\bullet$}}}
+\setlist[enumerate]{topsep=0.5ex,parsep=0.25ex,itemsep=0.25ex,listparindent=\parindent}% global
+\setlist[enumerate,2]{leftmargin=\parindent,labelsep=*,align=parleft,label=\alph*.}% local
+\setlist[description]{topsep=0.5ex,itemsep=0pt,listparindent=\parindent,leftmargin=\parindent,labelsep=1.5ex}
+
+\newenvironment{cquote}{%
+	\list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindent\rightmargin\leftmargin}%
+	\item\relax
+}{%
+	\endlist
+}% cquote
+
+\setlength{\topmargin}{-0.45in}							% move running title into header
+\setlength{\headsep}{0.25in}
+\setlength{\textheight}{9.0in}
+
+\newcommand{\CFAIcon}{\textsf{C\raisebox{\depth}{\rotatebox{180}A}}} % Cforall icon
+\newcommand{\CFA}{\protect\CFAIcon\xspace}				% CFA symbolic name
+\newcommand{\PAB}[1]{{\color{red}PAB: #1}}
+
+% \definecolor{mGreen}{rgb}{0,0.6,0}
+% \definecolor{mGray}{rgb}{0.5,0.5,0.5}
+% \definecolor{mPurple}{rgb}{0.58,0,0.82}
+% \definecolor{backgroundColour}{rgb}{0.95,0.95,0.92}
 
 \lstdefinestyle{CStyle}{
-    backgroundcolor=\color{backgroundColour},   
-    commentstyle=\color{mGreen},
-    keywordstyle=\color{magenta},
-    numberstyle=\tiny\color{mGray},
-    stringstyle=\color{mPurple},
-    basicstyle=\footnotesize,
+%    backgroundcolor=\color{backgroundColour},   
+%    commentstyle=\color{mGreen},
+%    keywordstyle=\color{magenta},
+	stringstyle=\small\tt,					% use typewriter font
+%    stringstyle=\color{mPurple},
+    columns=fullflexible,
+    basicstyle=\small\linespread{0.9}\sf,	% reduce line spacing and use sanserif font
+%   basicstyle=\footnotesize,
     breakatwhitespace=false,         
-    breaklines=true,                 
+%    breaklines=true,                 
     captionpos=b,                    
     keepspaces=true,                 
-    numbers=left,                    
-    numbersep=5pt,                  
-    showspaces=false,                
+%    numbers=left,                    
+%    numbersep=5pt,                  
+%    numberstyle=\tiny\color{mGray},
+%    showspaces=false,                
     showstringspaces=false,
-    showtabs=false,                  
-    tabsize=2,
-    language=C
-}
-
-%%
-%% \BibTeX command to typeset BibTeX logo in the docs
-\AtBeginDocument{%
-  \providecommand\BibTeX{{%
-    \normalfont B\kern-0.5em{\scshape i\kern-0.25em b}\kern-0.8em\TeX}}}
-
-
-%%
-%% end of the preamble, start of the body of the document source.
+%    showtabs=false,                  
+	showlines=true,							% show blank lines at end of code
+    tabsize=5,
+    language=C,
+	aboveskip=4pt,							% spacing above/below code block
+	belowskip=2pt,
+	xleftmargin=\parindent,			% indent code to paragraph indentation
+}
+\lstset{style=CStyle,moredelim=**[is][\color{red}]{@}{@}}
+\lstMakeShortInline@				% single-character for \lstinline
+
 \begin{document}
 
-%%
-%% The "title" command has an optional parameter,
-%% allowing the author to define a "short title" to be used in page headers.
-\title{Enumeration in Cforall}
-
-%%
-%% The "author" command and its associated commands are used to define
-%% the authors and their affiliations.
-%% Of note is the shared affiliation of the first two authors, and the
-%% "authornote" and "authornotemark" commands
-%% used to denote shared contribution to the research.
+\title{\vspace*{-0.5in}Enumeration in \CFA}
 \author{Jiada Liang}
 
-
-%%
-%% The abstract is a short summary of the work to be presented in the
-%% article.
+\maketitle
+
 \begin{abstract}
-    An enumeration, or enum in short, is a type that defines a list of named constant values in C. C uses integral type as the underlying representation of enum. Cforall extends C enum to allow more types, including custom types, to be used as enumeration inner representation.
+An enumeration is a type that defines a list of named constant values in C (and other languages).
+C uses an integral type as the underlying representation of an enumeration.
+\CFA extends C enumerations to allow all basic and custom types for the inner representation.
 \end{abstract}
 
-%%
-%% The code below is generated by the tool at http://dl.acm.org/ccs.cfm.
-%% Please copy and paste the code instead of the example below.
-%%
-
-
-%%
-%% This command processes the author and affiliation and title
-%% information and builds the first part of the formatted document.
-\maketitle
-
 \section{C-Style Enum}
-\begin{lstlisting}[style=CStyle, label{lst:weekday}]
+
+\CFA supports the C-Style enumeration using the same syntax and semantics.
+\begin{lstlisting}[label=lst:weekday]
 enum Weekday { Monday, Tuesday, Wednesday, Thursday=10, Friday, Saturday, Sunday };
 \end{lstlisting}
-Cforall supports the C-Style enumeration (C-enum for short). It has the same syntax as C and resembles the same language semantics. In code~\ref{lst:weekday} example, the syntax defines an enum class $Weekday$ with enumerators $Monday$, $Tuesday$, $Wednesday$, $Thursday$, $Friday$, $Saturday$ and $Sunday$ in order. The successor of $Tuesday$ is $Monday$ and the predecessor of $Tuesday$ is $Wednesday$. Enumerators have an integral type, either being explicitly initialized by an initializer or being assigned a value by the compiler. For example, $Thursday$ has been assigned with value $10$. If not explicitly initialized, the first value of an enum, $Monday$ in the $Weekday$ example, has the integer value 0. Other uninitialized enum value has a value that is equal to their successor $+ 1$. The enum value $Tuesday$, $Wednesday$, $Friday$, $Saturday$, and $Sunday$ have value 1, 2, 11, 12, and 13 respectively. 
-
-\begin{lstlisting}[label{lst:enum_scope}, style=CStyle]
-{
-    {
-        enum RGB {R, G, B};
-        int i = R  // i == 0
-    }
-    int j = G; // ERROR! G is not declared in this scope
-}
-\end{lstlisting}
-C-enums are unscoped: enumerators declared inside of an enum are visible in the enclosing scope of the enum class.
-
-\section{Cforall-Style Enum}
-\begin{lstlisting}[style=CStyle, label{lst:color}]
-enum Color(char *) { Red="R", Green="G", Blue="B"  };
-\end{lstlisting}
-A Cforall enumeration is parameterized by a type declared. Cforall allows any oType in the enum declaration, and values assigned to enumerators must be in the declared type.
-
-\section{Enumerable Type Traits}
-A trait is a collection of constraints in Cforall, which can be used to describe types. Cforall standard library defines traits to categorize types that are related enumeration features.
-\subsection{Enumerable}
-A type is enumerable if it can map an integer to a value. 
-\begin{lstlisting}[style=CStyle]
-forall(T)
-trait Enumerable {
-    T value( *class_name* , int );
-};
-\end{lstlisting}
-The parameter class name stands for the name of an enumeration class, Weekday, for example.
-
-\subsection{AutoInitializable}
-\begin{lstlisting}[style=CStyle]
+The example defines an @enum@ type @Weekday@ with ordered enumerators @Monday@, @Tuesday@, @Wednesday@, @Thursday@, @Friday@, @Saturday@ and @Sunday@.
+The successor of @Tuesday@ is @Monday@ and the predecessor of @Tuesday@ is @Wednesday@.
+A C enumeration has an integral type, with consecutive enumerator values assigned by the compiler starting at zero or explicitly initialized by the programmer.
+For example, @Monday@ to @Wednesday@ have values 0--2, @Thursday@ is set to @10@, and after it, @Friday@ to @Sunday@ have values 11--13.
+
+There are 3 attributes for an enumeration: position, label, and value:
+\begin{cquote}
+\small\sf
+\begin{tabular}{rccccccccccc}
+enum Weekday \{	& Monday,	& Tuesday,	& Wednesday,	& Thursday=10,	& Friday, 	& Saturday,	& Sunday \}; \\
+position		& 0			& 1			& 2				& 3				& 4			& 5			& 6			\\
+label			& Monday	& Tuesday	& Wednesday		& Thursday		& Friday 	& Saturday	& Sunday	\\
+value			& 0			& 1			& 2				& 10			& 11		& 12		& 13
+\end{tabular}
+\end{cquote}
+
+The enumerators of an enum are unscoped, i.e., enumerators declared inside of an enum are visible in the enclosing scope of the enum class.
+\begin{lstlisting}[label=lst:enum_scope]
+{
+	enum RGB { R, G, B };
+	int i = R  // i == 0
+}
+int j = G; // ERROR! G is not declared in this scope
+\end{lstlisting}
+
+\section{\CFA-Style Enum}
+
+A \CFA enumeration is parameterized by a type, which specifies the type for each enumerator.
+\CFA allows any object type for the enumerators, and values assigned to enumerators must be in the declared type.
+\begin{lstlisting}[label=lst:color]
+enum Colour( @char *@ ) { Red = "R", Green = "G", Blue = "B"  };
+\end{lstlisting}
+The type of @Colour@ is @char *@ and each enumerator is initialized with a C string.
+Only types have define an ordering can be automatically initialized (see Section~\ref{s:AutoInitializable}).
+
+
+% An instance of \CFA-enum (denoted as @<enum_instance>@) is a label for the defined enum name.
+% The label can be retrieved by calling the function @label( <enum_instance> )@.
+% Similarly, the @value()@ function returns the value used to initialize the \CFA-enum.
+
+A \CFA-enum is scoped: enumeration constants are not automatically exposed to the global scope.
+Enumeration constant can be referenced using qualified expressions like an aggregate that supports qualified references to its fields. The syntax of $qualified\_expression$ for \CFA-enum is the following:
+$$<qualified\_expression> := <enum\_type>.<enumerator>$$
+
+
+\subsection{enumeration instance}
+\begin{lstlisting}[label=lst:sample_cforall_enum_usage]
+Colour green = Colour.Green;
+\end{lstlisting}
+The ~\ref{lst:sample_cforall_enum_usage} example declares a $enumeration\ instance$ named @red@ and initializes it with $enumeration\ constant$ @Color.Red@.
+An enumeration instance is a data structure that captures attributes of an enumeration constant, which can be retrieved by functions $position( enumeration\ instance )$, $value( enumeration\ instance )$, and $label( enumeration\ instance )$. 
+\begin{lstlisting}
+int green_pos = position( green ); // 1
+char * green_value = value( green ); // "G"
+char * green_label = label( green ); // "Green"
+\end{lstlisting}
+An enumeration instance can be assigned to a variable or used as its position with type integer, its value with declared type T, or its label with type char *, and the compiler will resolve the usage as a type fits the context. 
+\begin{lstlisting}[label=lst:enum_inst_assign_int]
+int green_pos = green; // equivalent to position( green ); 
+\end{lstlisting}
+A resolution of an enumeration constant is $unambigious$ if only one of the attributes has the resolvable type.
+In example~\ref{lst:enum_inst_assign_int}, the right-hand side of the assignment expression expects integer type.
+The position of an enumeration is @int@, while the other two cannot be resolved as integers.
+The expression unambiguously returns the position of @green@.
+\begin{lstlisting}[label=lst:enum_inst_assign_string]
+char * green_value = green; // equivalent to value( green ); 
+\end{lstlisting}
+On the other hand, the resolution of an enumeration constant is $ambigious$ if multiple attributes have the expected type.
+In example~\ref{lst:enum_inst_assign_string}, both value and label have the expected type @char *@.
+When a resolution is ambiguous, a \textit{resolution precedence} applies: $$value > position > label$$
+\CFA uses resolution distance to describe if one type can be used as another. While \CFA calculates the resolution distance between the expected type and types of all three attributes, it would not choose the attribute with the closest distance. Instead, when resolving an enumeration constant, \CFA always chooses value whenever it is a possible resolution (resolution distance is not infinite), followed by position, then label. 
+\begin{lstlisting}[label=lst:enum_inst_precedence]
+enum(double) Foo { Bar };
+int tee = Foo.Bar; // value( Bar );
+\end{lstlisting}
+In the example~\ref{lst:enum_inst_precedence}, while $position( Bar )$ has the closest resolution among the three attributes, $Foo.Bar$ is resolved as $value( Bar )$ because of the resolution precedence.
+
+Although \CFA enumeration captures three different attributes, an instance of enumeration does not occupy extra memory.
+The @sizeof@ \CFA enumeration instance is always 4 bytes, the same amount of memory to store a C enumeration instance.
+It comes from the fact that:
+\begin{enumerate}
+\item
+a \CFA enumeration is always statically typed;
+\item
+it is always resolved as one of its attributes in terms of real usage.
+\end{enumerate}
+When creating the enumeration instance green and assigns it with the enumeration constant @Color.Green@, the compilers essentially allocate an integer variables and store the position 1.
+The invocations of $positions()$, $value()$, and $label()$ turn into calls to special functions defined in the prelude:
+\begin{lstlisting}[label=lst:companion_call]
+position( green );
+>>> position( Colour, 1 ) -> int
+value( green );
+>>> value( Colour, 1 ) -> T
+label( green );
+>>> label( Colour, 1) -> char *
+\end{lstlisting}
+@T@ represents the type declared in the \CFA enumeration defined and @char *@ in the example. 
+These generated functions are $Companion Functions$, they take an $companion$ object and the position as parameters.
+
+\subsection{Companion Object and Companion Function}
+
+\begin{lstlisting}[caption={Enum Type Functions}, label=lst:cforall_enum_functions]
+forall( T )  {
+	struct Companion {
+		const T * const values;
+		const char** const labels;
+			int length;
+	};
+}
+\end{lstlisting}
+\CFA creates an object of Companion for every \CFA-enumeration. A companion object has the same name as the enumeration is defined for.
+A companion object stores values and labels of enumeration constants, in the order of the constants defined in the enumeration.
+
+\CFA generates the definition of companion functions. Because \CFA implicitly stores enumeration instance as its position, the companion function $position$ does nothing but returns the position it passes it.
+Companions function $value$ and $label$ return the array item at the given position of $values$ and $labels$, respectively.
+\begin{lstlisting}[label=lst:companion_definition]
+int position( Companion o, int pos ) { return pos; }
+T value( Companion o, int pos ) { return o.values[ pos ]; }
+char * label( Companion o, int pos ) { return o.labels[ pos ]; }
+\end{lstlisting}
+Notably, the Companion structure definition, and all companion objects, are visible to the users.
+A user can retrieve values and labels defined in an enumeration by accessing the values and labels directly, or indirectly by calling Companion functions $values$ and $labels$
+\begin{lstlisting}[label=lst:companion_definition_values_labels]
+Colour.values; // read the Companion's values
+values( Colour ); // Same as Colour.values
+\end{lstlisting}
+
+\subsection{User Define Enumeration Functions}
+
+The Companion objects make extending features for \CFA enumeration easy. 
+
+\begin{lstlisting}[label=lst:companion_user_definition]
+char * charastic_string( Companion o, int position ) { 
+	return sprintf("Label: %s; Value: %s", label( o, position ), value( o, position) ); 
+}
+printf( charactic_string ( Color, 1 ) );
+>>> Label: G; Value: G
+\end{lstlisting}
+Defining a function takes a Companion object effectively defines functions for all \CFA enumeration.
+
+The \CFA compiler turns a function call that takes an enumeration instance as a parameter into a function call with a companion object plus a position.
+Therefore, a user can use the syntax with a user-defined enumeration function call:
+\begin{lstlisting}[label=lst:companion_user_definition]
+charactic_string ( Color.Green ); // equivalent to charactic_string ( Color, 1 )
+>>> Label: G; Value: G
+\end{lstlisting}
+Similarly, the user can work with the enumeration type itself: (see section ref...)
+\begin{lstlisting}[ label=lst:companion_user_definition]
+void print_enumerators ( Companion o ) { 
+	for ( c : Companion o ) {
+		sout | label (c) | value( c ) ;
+	} 
+}
+print_enumerators( Colour );
+\end{lstlisting}
+
+\subsection{Runtime Enumeration}
+
+The Companion structure definition is visible to users, and users can create an instance of Companion object themselves, which effectively constructs a \textit{Runtime Enumeration}.
+\begin{lstlisting}[ label=lst:runtime_enum ]
+const char values[] = { "Hello", "World" };
+const char labels[] = { "First", "Second" };
+Companion (char *) MyEnum = { .values: values, .labels: labels, .length: 2 };
+\end{lstlisting}
+A runtime enumeration can be used to call enumeration functions.
+\begin{lstlisting}[ label=lst:runtime_enum_usage ]
+sout | charatstic_string( MyEnum, 1 );
+>>> Label: Second; Value: World
+\end{lstlisting}
+However, a runtime enumeration cannot create an enumeration instance, and it does not support enum-qualified syntax.
+\begin{lstlisting}[ label=lst:runtime_enum_usage ]
+MyEnum e = MyEnum.First; // Does not work: cannot create an enumeration instance e, 
+			            // and MyEnum.First is not recognizable
+\end{lstlisting}
+During the compilation, \CFA adds enumeration declarations to an enumeration symbol table and creates specialized function definitions for \CFA enumeration. \CFA does not recognize runtime enumeration during compilation and would not add them to the enumeration symbol table, resulting in a lack of supports for runtime enumeration.
+
+\section{Enumeration Features}
+
+A trait is a collection of constraints in \CFA, which can be used to describe types.
+The \CFA standard library defines traits to categorize types with related enumeration features.
+
+\subsection{Auto Initializable}
+\label{s:AutoInitializable}
+
+TODO: make the initialization rule a separate section. 
+
+If no explicit initializer is given to an enumeration constant, C initializes the first enumeration constant with value 0, and the other enumeration constant has a value equal to its $predecessor+1$.
+\CFA enumerations have the same rule in enumeration constant initialization.
+However, not all types can be automatically initialized by \CFA because the meaning of $zero$, $one$, and addition operator may not be well-defined.
+
+A type is auto-Initializable if it has defined @zero_t@, @one_t@, and an addition operator.
+\begin{lstlisting}
 forall(T)
 trait AutoInitializable {
-  void ?()( T & t, zero_t );
-  void ?()( T & t, one_t );
-  S& ?+=?( T & t, one_t );
-  void ?{}( T &, T ); 
-  T ?{}( T &, T ); 
-};
-\end{lstlisting}
-
-\subsection{AutoInitializable}
-\begin{lstlisting}[style=CStyle]
-forall(T)
-trait AutoInitializable {
-  void ?()( T & t, zero_t );
-  void ?()( T & t, one_t );
-  S& ?+=?( T & t, one_t );
-  void ?{}( T &, T ); 
-  T ?{}( T &, T ); 
-};
-\end{lstlisting}
-A type is AutoInitializable if it has defined a zero\_t constructor, a one\_t constructor, an addition assignment operator, a copy constructor, and a copy assignment operator.
-
-\subsection{Enumerable Type}
-\begin{lstlisting}[style=CStyle]
-forall(T)
-trait enumerable {
-  void ?()( T & t, zero_t );
-  void ?()( T & t, one_t );
-  S& ?+=?( T & t, one_t );
-  void ?{}( T &, T ); 
-  T ?{}( T &, T ); 
-};
-\end{lstlisting}
-
-
-
-
-
-(Should change the definition of enumerable to something else. Maybe auto-constructible. If a type is not auto-constructible, all enumeration must be explicitly initialized)
-\begin{lstlisting}[caption={An example enumerable type}, label{lst:sample_enumerable}, style=CStyle]
-struct Type { int i; };
-void ?()( Type & t, zero_t ) { t.i = 0; };
-void ?()( Type & t, one_t ) { t.i = 1; };
-int ?!=?( Type t, zero_t ) { return t.i != 0; };
-S& ?+=?( Type & t, one_t ) { t.i += 1; return t; };
-void ?()( Type & t, Type rhs ) { t.i = rhs.i; };
-Type ?()( Type & t, Type rhs ) { t.i = rhs.i; return t; };
-\end{lstlisting}
-
-A Cforall-enum is a C-enum parameterized by an enumerable type. For example,  $enum(int)$ turns a C-enum into a Cforall-enum.
-\begin{lstlisting}[caption={An example Cforall enum}, label{lst:sample_cforall_enum}, style=CStyle]
-enum Color(Type) { Red, Green, Blue };
-
-> Type Color.values[] = { 0, values[0]++, values[1]++ }; 
-> enum Color.Label { Red_Label, Green_Label, Blue_Label };
-\end{lstlisting}
-Declaring a Cforall-enum, the compiler defines a C-enum names every element in the Cforall-enum, and an array that stores Cforall enumeration values. 
-
-\subsection{Cforall Enumerations Behaviour}
-An instance of Cforall-enum (denoted as $<enum\_instance>$) has a label, the defined enum name. The label can be retrieved by calling the function $label()$ on a $<enum\_instance>$. The $value()$ function on the other hand returns the value used to initialize the Cforall-enum.
-
-Cforall-enum supports a qualified expression. The syntax of the qualified expression for Cforall-enum is $$<enum\_type\_name>.<enum\_instance\_name>$$. In the $Color$ example, $Color$ is a $<enum\_type\_name>$ and $Red$, $Green$, $Blue$ are $<enum\_instance\_name>$. 
-
-\begin{lstlisting}[caption={An example Cforall enum}, label{lst:sample_cforall_enum_usage}, style=CStyle]
-enum Color red = Color.Red;
-> enum Color.Label red = = Color.Label.Red_Label; 
-Type instance = Color.Red;
-> Type instance = Color.values[ Color.Label.Red_Label ];
-\end{lstlisting}
-
-The expression $Color.Red$ is overloaded to represent both $value(Color.Red)$ and $label(Color.Red)$. The expression returns the $label(Color.Red)$ by default but returns $value()$ whenever the $value()$ is a closer candidate in the context. [more explanation] In \ref{lst:sample_cforall_enum_usage}, when assigned to an enum variable, $Color.Red$ returns the label. This is to reduce the memory to store a Cforall-enum variable. In an assignment expression when the left-hand-side expects a $Type$, the resolution finds $value(Color.Red)$ is a better candidate than $label(Color.Red)$, and returns the value instead.
-
-\subsection{Enum Type Functions}
-\begin{lstlisting}[caption={Enum Type Functions}, label{lst:cforall_enum_functions}, style=CStyle]
-enum Color(string) { // assume String has been defined as an enumerable type
-    R = "Red", G = "Green", B = "Blue"
-};
-values( Color );
-> [ String("Red"), String("Green"), String("Blue") ];
-label_strings( Color );
-> [ "R", "G", "B" ];
-enum Color green = Color.G;
-
-label_string( Color, green );
-> "G"
-label( Color, green );
-> 1
-value( Color, green ) ;
-> "Green"
-value( Color, "G" );
-> "Green"
-label( Color, "G" );
-> 1
-value( Color, "DNE" );
-> (null)
-value( Color, 1 ); // "1" is the label "G"
-> "Green"
-\end{lstlisting}
-Names of labels are distinct in an enum declaration. Cforall therefore allows indexing an enum value with its string representation of a label.
+	void ?()( T & t, zero_t );
+	void ?()( T & t, one_t );
+	S ?+?( T & t, one_t );
+};
+\end{lstlisting}
+An example of user-defined @AutoInitializable@ would look like the following:
+\begin{lstlisting}[label=lst:sample_auto_Initializable]
+struct Odd { int i; };
+void ?()( Odd & t, zero_t ) { t.i = 1; };
+void ?()( Odd & t, one_t ) { t.i = 2; };
+Odd ?+?( Odd t1, Odd t2 ) 
+	{ return Odd( t1.i + t2.i); };
+\end{lstlisting}
+When an enumeration declares an AutoInitializable as its type, no explicit initialization is necessary. 
+\begin{lstlisting}[label=lst:sample_auto_Initializable_usage]
+enum AutoInitUsage(Odd) {
+	A, B, C = 6, D
+};
+\end{lstlisting}
+
+In the example~\ref{lst:sample_auto_Initializable_usage_gen}, because no initializer is specified for the first enumeration constant @A@, \CFA initializes it with the value of @zero_t@, which is 1.
+@B@ and @D@ have the values of their $predecessor + one_t$, while @one_t@ has the value 2.
+Therefore, the enumeration is initialized as the following:
+\begin{lstlisting}[label=lst:sample_auto_Initializable_usage_gen]
+enum AutoInitUsage(Odd) {
+	A=1, B=3, C = 6, D=8
+};
+\end{lstlisting}
+In \CFA, integral types, float types, and imaginary numbers are example types that are AutoInitialiable.
+\begin{lstlisting}[label=lst:letter]
+enum Alphabet(int) {
+	A='A', B, C, D, E, F, G, H, I, J, K, L, M,
+	N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
+	a='a', b, c, d, e, f, g, h, i, j, k, l, m,
+	n, o, p, q, r, s, t, u, v, w, x, y, z
+};
+print( "%c, %c, %c", Alphabet.F, Alphabet.o, Alphabet.o );
+>>> F, o, o
+\end{lstlisting}
 
 \subsection{Iteration and Range}
-A Cforall enum is iterable and supports range function.
-\begin{lstlisting}[caption={Range Functions}, label{lst:range_functions}, style=CStyle]
-struct string;
-enum(string) Weekday( 
-    Monday = "M", Tuesday = "Tu", ...
-};
-for ( i; Weekday ) { sout | i; }
->> M Tu W Th F Sat Sun
-for ( Monday ~= Tuesday )
->> M Tu
+
+It is convenient to iterate over a \CFA enumeration.
+Here is the basic usage:
+\begin{lstlisting}[label=lst:range_functions]
+for ( Alphabet ah; Alphabet; ) {
+	printf( "%d ", ah );
+}
+>>> A B C (...omit the rest)
+\end{lstlisting}
+The for-loop uses the enumeration type @Alphabet@ as range.
+When that happens, \CFA iterates all enumerators in the order they defined in the enumeration.
+@'ch'@ is the iterating enumerator, and it returns the value of an Alphabet in this context according to the precedence rule.
+
+\CFA offers a shorthand for iterating all enumeration constants: 
+\begin{lstlisting}[label=lst:range_functions]
+for ( Alphabet ch ) {
+	printf( "%d ", ch );
+}
+>>> A B C (...omit the rest)
+\end{lstlisting}
+
+Enumeration supports the \CFA loop control syntax for for-loop.
+\begin{lstlisting}[label=lst:range_functions]
+for ( Alphabet.D )
+for ( ch; Alphabet.g ~ Alphabet.z )
+for ( Alphabet ch; Alphabet.R ~ Alphabet.X ~ 2 )
+\end{lstlisting}
+Notably, the meaning of "step" of iteration has changed for enumeration.
+Consider the following example:
+\begin{lstlisting}[label=lst:range_functions]
+enum(int) Sequence {
+	A = 10, B = 12, C = 14;  
+}
+for ( s; Sequence.A ~ Sequence.C ) {
+	printf( "%d ", s ); 
+}
+
+>>> 10 12 14
+
+for ( s; Sequence.A ~ Sequence.A ~ 2 ) {
+	printf( "%d ", s ); 
+}
+>>> 10 14
+\end{lstlisting}
+The range iteration of enumeration does not return the @current_value++@ until it reaches the upper bound.
+The semantics is to return the next enumeration constant.
+If a stepping is specified, 2 for example, it returns the 2 enumeration constant after the current one, rather than the @current+2@.
+
+It is also possible to iterate over an enumeration's labels, implicitly or explicitly:
+\begin{lstlisting}[label=lst:range_functions_label_implicit]
+for ( char * ch; Alphabet )
+\end{lstlisting}
+This for-loop implicitly iterates every label of the enumeration, because a label is the only valid resolution to the ch with type @char *@ in this case.
+If the value can also be resolved as the @char *@, you might iterate the labels explicitly with the array iteration.
+\begin{lstlisting}[label=lst:range_functions_label_implicit]
+for ( char * ch; labels( Alphabet ) )
 \end{lstlisting}
 
 \section{Implementation}
 
-\subsection{Companion Object}
-The intuition to create a companion object is that functions that support enumeration features need static information of an enumeration class. For example, values() returns an array of values defined for the enumeration. $label( Color, "G" )$ needs information about enum names defined for the enum class $Color$. Theoretically, enum-type functions can be defined as functions that take $TypeName$ expression as the first parameter. An alternative approach is to define that "companion object".
-
-\begin{lstlisting}[caption={Enum Type Functions}, label{lst:cforall_enum_functions}, style=CStyle]
-struct string;
-enum Color( string ) { 
-    R = "Red", G = "Green", B = "Blue"
-};
-
-forall( T | enumerable(T) )  {
-    struct Companion {
-        T* values;
-        char** labels;
-    };
-}
->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-enum Color.Label;
-Companion( string ) Color = { 
-    .values = [ "Red", "Green", "Blue" ],
-    .labels = [ "R", "G", "B" ]
-};
->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-forall( T | enumerable(T) )
-T value( Companion companion, int index ) { return companion.values[ index ]; } 
-T value( Companion, enum Color.Label );
-char* label( Companion companion, int index ) { return companion.values[ index ]; }
-char* label( Companion, enum Color.Label );
-
-\end{lstlisting}
-
-
-\subsection{Companion Trait}
-Users can define the companion object themselves. A companion object should define an array of any type called values and an array of strings representing a label. Defining a companion object effectively creates a new enumerable type. 
-
-\subsection{Companion Mapping}
-
-
-
-\begin{lstlisting}[caption={Enum Type Functions}, label{lst:cforall_enum_functions}, style=CStyle]
-
-\end{lstlisting}
-%%
-%% If your work has an appendix, this is the place to put it.
-\appendix
-
+\CFA places the definition of Companion structure and non-parameterized Companion functions in the prelude, visible globally.
+
+\subsection{Declaration}
+
+The qualified enumeration syntax is dedicated to \CFA enumeration.
+\begin{lstlisting}[label=lst:range_functions]
+enum (type_declaration) name { enumerator = const_expr, enumerator = const_expr, ... }
+\end{lstlisting}
+A compiler stores the name, the underlying type, and all enumerators in an @enumeration table@.
+During the $Validation$ pass, the compiler links the type declaration to the type's definition.
+It ensures that the name of an enumerator is unique within the enumeration body, and checks if all values of the enumerator have the declaration type.
+If the declared type is not @Auto Initializable@, \CFA rejects the enumeration definition.
+Otherwise, it attempts to initialize enumerators with the enumeration initialization pattern. (a reference to a future initialization pattern section) 
+
+\begin{lstlisting}[label=lst:init]
+struct T { ... };
+void ?{}( T & t, zero_t ) { ... };
+void ?{}( T & t, one_t ) { ... };
+T ?+?( T & lhs, T & rhs ) { ... };
+
+enum (T) Sample { 
+	Zero: 0 /* zero_t */, 
+	One: Zero + 1 /* ?+?( Zero, one_t ) */ , ...
+};
+\end{lstlisting}
+Challenge: \\
+The value of an enumerator, or the initializer, requires @const_expr@.
+While previously getting around the issue by pushing it to the C compiler, it might not work anymore because of the user-defined types, user-defined @zero_t@, @one_t@, and addition operation.
+Might not be able to implement a \emph{correct} static check.
+
+\CFA $autogens$ a Companion object for the declared enumeration.
+\begin{lstlisting}[label=lst:companion]
+Companion( T ) Sample {
+	.values: { 0, 0+1, 0+1+1, 0+1+1+1, ... }, /* 0: zero_t, 1: one_t, +: ?+?{} */
+	.labels: { "Zero", "One", "Two", "Three", ...},
+	.length: /* number of enumerators */
+};
+\end{lstlisting}
+\CFA stores values as intermediate expressions because the result of the function call to the function @?+?{}(T&, T&)@ is statically unknown to \CFA.
+But the result is computed at run time, and the compiler ensures the @values@ are not changed.
+
+\subsection{qualified expression}
+
+\CFA uses qualified expression to address the scoping of \CFA-enumeration. 
+\begin{lstlisting}[label=lst:qualified_expression]
+aggregation_name.field;
+\end{lstlisting}
+The qualified expression is not dedicated to \CFA enumeration.
+It is a feature that is supported by other aggregation in \CFA as well, including a C enumeration.
+When C enumerations are unscoped, the qualified expression syntax still helps to disambiguate names in the context.
+\CFA recognizes if the expression references a \CFA aggregation by searching the presence of @aggregation_name@ in the \CFA enumeration table.
+If the @aggregation_name@ is identified as a \CFA enumeration, the compiler checks if @field@ presents in the declared \CFA enumeration.
+
+\subsection{\lstinline{with} statement/statement}
+
+\emph{Work in Progress}
+
+Instead of qualifying an enumeration expression every time, one can use the @with@ to expose enumerators to the current scope so that they are directly accessible.
+
+\subsection{Instance Declaration}
+
+\emph{Work in Progress}
+
+\begin{lstlisting}[label=lst:declaration]
+enum Sample s1;
+Sample s2;
+\end{lstlisting}
+A declaration of \CFA enumeration instance that has no difference than a C enumeration or other \CFA aggregation.
+The compiler recognizes the type of a variable declaration by searching the name in all possible types.
+The @enum@ keyword is not necessary but helps to disambiguate types (questionable).
+The generated code for a \CFA enumeration declaration is utterly an integer, which is meant to store the position.
+\begin{lstlisting}[label=lst:declaration]
+int s1;
+int s2;
+\end{lstlisting}
+
+\subsection{Compiler Representation}
+
+\emph{Work in Progress}
+
+The internal representation of an enumeration constant is @EnumInstType@.
+The minimum information an @EnumInstType@ stores is a reference to the \CFA-enumeration declaration and the position of the enumeration constant.
+\begin{lstlisting}[label=lst:EnumInstType]
+class EnumInstType {
+	EnumDecl enumDecl;
+	int position;
+};
+\end{lstlisting}
+
+\subsection{Unification and Resolution }
+
+\emph{Work in Progress}
+
+\begin{lstlisting}
+enum Colour( char * ) { Red = "R", Green = "G", Blue = "B"  };
+\end{lstlisting}
+The @EnumInstType@ is convertible to other types.
+A \CFA enumeration expression is implicitly \emph{overloaded} with its three different attributes: value, position, and label.
+The \CFA compilers need to resolve an @EnumInstType@ as one of its attributes based on the current context. 
+
+\begin{lstlisting}[caption={Null Context}, label=lst:null_context]
+{
+	Colour.Green;
+}
+\end{lstlisting}
+In example~\ref{lst:null_context}, the environment gives no information to help with the resolution of @Colour.Green@.
+In this case, any of the attributes is resolvable.
+According to the \textit{precedence rule}, the expression with @EnumInstType@ resolves as @value( Colour.Green )@.
+The @EnumInstType@ is converted to the type of the value, which is statically known to the compiler as @char *@.
+When the compilation reaches the code generation, the compiler outputs code for type @char *@ with the value @"G"@.
+\begin{lstlisting}[caption={Null Context Generated Code}, label=lst:null_context]
+{
+	"G";
+}
+\end{lstlisting}
+\begin{lstlisting}[caption={int Context}, label=lst:int_context]
+{
+	int g = Colour.Green;
+}
+\end{lstlisting}
+The assignment expression gives a context for the EnumInstType resolution.
+The EnumInstType is used as an @int@, and \CFA needs to determine which of the attributes can be resolved as an @int@ type.
+The functions $Unify( T1, T2 ): bool$ take two types as parameters and determine if one type can be used as another.
+In example~\ref{lst:int_context}, the compiler is trying to unify @int@ and @EnumInstType@ of @Colour@.
+$$Unification( int, EnumInstType<Colour> )$$ which turns into three Unification call
+\begin{lstlisting}[label=lst:attr_resolution_1]
+{
+	Unify( int, char * ); // unify with the type of value
+	Unify( int, int ); // unify with the type of position
+	Unify( int, char * ); // unify with the type of label
+}
+\end{lstlisting}
+\begin{lstlisting}[label=lst:attr_resolution_precedence]
+{
+	Unification( T1, EnumInstType<T2> ) {
+		if ( Unify( T1, T2 ) ) return T2;
+		if ( Unify( T1, int ) ) return int;
+		if ( Unify( T1, char * ) ) return char *;
+		Error: Cannot Unify T1 with EnumInstType<T2>;
+	}
+}
+\end{lstlisting}
+After the unification, @EnumInstType@ is replaced by its attributes.
+
+\begin{lstlisting}[caption={Unification Functions}, label=lst:unification_func_call]
+{
+	T2 foo ( T1 ); // function take variable with T1 as a parameter
+	foo( EnumInstType<T3> ); // Call foo with a variable has type EnumInstType<T3>
+	>>>> Unification( T1, EnumInstType<T3> )
+}
+\end{lstlisting}
+% The conversion can work backward: in restrictive cases, attributes of can be implicitly converted back to the EnumInstType. 
+Backward conversion:
+\begin{lstlisting}[caption={Unification Functions}, label=lst:unification_func_call]
+{
+	enum Colour colour = 1;
+}
+\end{lstlisting}
+
+\begin{lstlisting}[caption={Unification Functions}, label=lst:unification_func_call]
+{
+   Unification( EnumInstType<Colour>, int ) >>> label
+}
+\end{lstlisting}
+@int@ can be unified with the label of Colour.
+@5@ is a constant expression $\Rightarrow$ Compiler knows the value during the compilation $\Rightarrow$ turns it into 
+\begin{lstlisting}
+{
+   enum Colour colour = Colour.Green; 
+}
+\end{lstlisting}
+Steps:
+\begin{enumerate}
+\item
+identify @1@ as a constant expression with type @int@, and the value is statically known as @1@
+\item
+@unification( EnumInstType<Colour>, int )@: @position( EnumInstType< Colour > )@
+\item
+return the enumeration constant at the position 1
+\end{enumerate}
+\begin{lstlisting}
+{
+	enum T (int) { ... } // Declaration
+	enum T t = 1; 
+}
+\end{lstlisting}
+Steps:
+\begin{enumerate}
+\item
+identify @1@ as a constant expression with type @int@, and the value is statically known as @1@
+\item
+@unification( EnumInstType<Colour>, int )@: @value( EnumInstType< Colour > )@
+\item
+return the FIRST enumeration constant that has the value 1, by searching through the values array
+\end{enumerate}
+The downside of the precedence rule: @EnumInstType@ $\Rightarrow$ @int ( value )@ $\Rightarrow$ @EnumInstType@ may return a different @EnumInstType@ because the value can be repeated and there is no way to know which one is expected $\Rightarrow$ want uniqueness 
 
 \end{document}
-\endinput
-%%
-%% End of file `sample-manuscript.tex'.
+
+% Local Variables: %
+% tab-width: 4 %
+% compile-command: "pdflatex enum.tex" %
+% End: %
Index: libcfa/src/iostream.cfa
===================================================================
--- libcfa/src/iostream.cfa	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ libcfa/src/iostream.cfa	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Oct 19 21:10:10 2023
-// Update Count     : 1801
+// Last Modified On : Sat Nov 11 07:06:27 2023
+// Update Count     : 1803
 //
 
@@ -1001,4 +1001,6 @@
 				} // if
 			} // if
+			// FIX ME: CFA strings need to be modified to NOT change the argument for this case, then this can be removed.
+			if ( rwd > 0 && args == 0 ) f.s[0]= '\0';	// read failed => no pattern match => set string to null
 		} else {
 			if ( f.flags.delimiter ) {					// getline
@@ -1041,4 +1043,5 @@
 				} // if
 			} // if
+			if ( rwd > 0 && args == 0 ) f.s[0]= '\0';	// read failed => no pattern match => set string to null
 		} // if
 		if ( args == 1 && eof( is ) ) {					// data but scan ended at EOF
Index: c/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,3040 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// Convert.cpp -- Convert between the new and old syntax trees.
-//
-// Author           : Thierry Delisle
-// Created On       : Thu May 09 15::37::05 2019
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed Apr 20 13:58:00 2022
-// Update Count     : 43
-//
-
-#include "Convert.hpp"
-
-#include <deque>
-#include <unordered_map>
-
-#include "AST/Attribute.hpp"
-#include "AST/Copy.hpp"
-#include "AST/Decl.hpp"
-#include "AST/Expr.hpp"
-#include "AST/Init.hpp"
-#include "AST/Stmt.hpp"
-#include "AST/TranslationUnit.hpp"
-#include "AST/TypeSubstitution.hpp"
-
-#include "SymTab/Autogen.h"
-#include "SynTree/Attribute.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/TypeSubstitution.h"
-
-#include "Validate/FindSpecialDecls.h"
-
-//================================================================================================
-// Utilities
-template<template <class...> class C>
-struct to {
-	template<typename T>
-	static auto from( T && v ) -> C< typename T::value_type > {
-		C< typename T::value_type > l;
-		std::move(std::begin(v), std::end(v), std::back_inserter(l));
-		return l;
-	}
-};
-
-//================================================================================================
-namespace ast {
-// These are the shared local information used by ConverterNewToOld and
-// ConverterOldToNew to update the global information in the two versions.
-
-static ast::ptr<ast::Type> sizeType = nullptr;
-static const ast::FunctionDecl * dereferenceOperator = nullptr;
-static const ast::StructDecl   * dtorStruct = nullptr;
-static const ast::FunctionDecl * dtorStructDestroy = nullptr;
-
-}
-
-//================================================================================================
-class ConverterNewToOld : public ast::Visitor {
-	BaseSyntaxNode * node = nullptr;
-	using Cache = std::unordered_map< const ast::Node *, BaseSyntaxNode * >;
-	Cache cache;
-
-	// Statements can no longer be shared.
-	// however, since StmtExprResult is now implemented, need to still maintain
-	// readonly references.
-	Cache readonlyCache;
-
-	template<typename T>
-	struct Getter {
-		ConverterNewToOld & visitor;
-
-		template<typename U, enum ast::Node::ref_type R>
-		T * accept1( const ast::ptr_base<U, R> & ptr ) {
-			if ( ! ptr ) return nullptr;
-			ptr->accept( visitor );
-			T * ret = strict_dynamic_cast< T * >( visitor.node );
-			visitor.node = nullptr;
-			return ret;
-		}
-
-		template<typename U>
-		std::list< T * > acceptL( const U & container ) {
-			std::list< T * > ret;
-			for ( auto ptr : container ) {
-				ret.emplace_back( accept1( ptr ) );
-			}
-			return ret;
-		}
-	};
-
-	template<typename T>
-	Getter<T> get() {
-		return Getter<T>{ *this };
-	}
-
-	Label makeLabel(Statement * labelled, const ast::Label& label) {
-		// This probably will leak memory, but only until we get rid of the old tree.
-		if ( nullptr == labelled && label.location.isSet() ) {
-			labelled = new NullStmt();
-			labelled->location = label.location;
-		}
-		return Label(
-			label.name,
-			labelled,
-			get<Attribute>().acceptL(label.attributes)
-		);
-	}
-
-	template<template <class...> class C>
-	std::list<Label> makeLabelL(Statement * labelled, const C<ast::Label>& labels) {
-		std::list<Label> ret;
-		for (auto label : labels) {
-			ret.push_back( makeLabel(labelled, label) );
-		}
-		return ret;
-	}
-
-	/// get new qualifiers from old type
-	Type::Qualifiers cv( const ast::Type * ty ) { return { ty->qualifiers.val }; }
-
-	/// returns true and sets `node` if in cache
-	bool inCache( const ast::Node * node ) {
-		auto it = cache.find( node );
-		if ( it == cache.end() ) return false;
-		this->node = it->second;
-		return true;
-	}
-
-public:
-	Declaration * decl( const ast::Decl * declNode ) {
-		return get<Declaration>().accept1( ast::ptr<ast::Decl>( declNode ) );
-	}
-
-private:
-	void declPostamble( Declaration * decl, const ast::Decl * node ) {
-		decl->location = node->location;
-		// name comes from constructor
-		// linkage comes from constructor
-		decl->extension = node->extension;
-		decl->uniqueId = node->uniqueId;
-		// storageClasses comes from constructor
-		this->node = decl;
-	}
-
-	const ast::DeclWithType * declWithTypePostamble (
-			DeclarationWithType * decl, const ast::DeclWithType * node ) {
-		cache.emplace( node, decl );
-		decl->mangleName = node->mangleName;
-		decl->scopeLevel = node->scopeLevel;
-		decl->asmName = get<Expression>().accept1( node->asmName );
-		// attributes comes from constructor
-		decl->isDeleted = node->isDeleted;
-		// fs comes from constructor
-		declPostamble( decl, node );
-		return nullptr;
-	}
-
-	const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {	
-		if ( inCache( node ) ) {
-			return nullptr;
-		}
-		auto bfwd = get<Expression>().accept1( node->bitfieldWidth );
-		auto type = get<Type>().accept1( node->type );
-		auto attr = get<Attribute>().acceptL( node->attributes );
-
-		// This field can be unset very early on (Pre-FixReturnTypes).
-		auto newType = (type) ? type->clone() : nullptr;
-
-		auto decl = new ObjectDecl(
-			node->name,
-			Type::StorageClasses( node->storage.val ),
-			LinkageSpec::Spec( node->linkage.val ),
-			bfwd,
-			newType,
-			nullptr, // prevent infinite loop
-			attr,
-			Type::FuncSpecifiers( node->funcSpec.val )
-		);
-
-		// handles the case where node->init references itself
-		// xxx - does it really happen?
-		declWithTypePostamble(decl, node);
-		auto init = get<Initializer>().accept1( node->init );
-		decl->init = init;
-
-		this->node = decl;
-		return nullptr;
-	}
-
-	const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-
-		// function decl contains real variables that the type must use.
-		// the structural change means function type in and out of decl
-		// must be handled **differently** on convert back to old.
-		auto ftype = new FunctionType(
-			cv(node->type),
-			(bool)node->type->isVarArgs
-		);
-		ftype->returnVals = get<DeclarationWithType>().acceptL(node->returns);
-		ftype->parameters = get<DeclarationWithType>().acceptL(node->params);
-
-		ftype->forall = get<TypeDecl>().acceptL( node->type_params );
-		if (!node->assertions.empty()) {
-			assert(!ftype->forall.empty());
-			// find somewhere to place assertions back, for convenience it is the last slot
-			ftype->forall.back()->assertions = get<DeclarationWithType>().acceptL(node->assertions);
-		}
-
-		visitType(node->type, ftype);
-
-		auto decl = new FunctionDecl(
-			node->name,
-			Type::StorageClasses( node->storage.val ),
-			LinkageSpec::Spec( node->linkage.val ),
-			ftype,
-			//get<FunctionType>().accept1( node->type ),
-			{},
-			get<Attribute>().acceptL( node->attributes ),
-			Type::FuncSpecifiers( node->funcSpec.val )
-		);
-		cache.emplace( node, decl );
-		decl->statements = get<CompoundStmt>().accept1( node->stmts );
-		decl->withExprs = get<Expression>().acceptL( node->withExprs );
-		if ( ast::dereferenceOperator == node ) {
-			Validate::dereferenceOperator = decl;
-		}
-		if ( ast::dtorStructDestroy == node ) {
-			Validate::dtorStructDestroy = decl;
-		}
-		return declWithTypePostamble( decl, node );
-	}
-
-	// InlineMemberDecl vanish after EnumAndPointerDecay pass so no necessary to implement NewToOld
-	const ast::DeclWithType * visit( const ast::InlineMemberDecl * node ) override final {	
-		assert( false );
-		(void) node;
-		return nullptr;
-	}
-
-	const ast::Decl * namedTypePostamble( NamedTypeDecl * decl, const ast::NamedTypeDecl * node ) {
-		// base comes from constructor
-		decl->assertions = get<DeclarationWithType>().acceptL( node->assertions );
-		declPostamble( decl, node );
-		return nullptr;
-	}
-
-	const ast::Decl * visit( const ast::TypeDecl * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto decl = new TypeDecl(
-			node->name,
-			Type::StorageClasses( node->storage.val ),
-			get<Type>().accept1( node->base ),
-			(TypeDecl::Kind)(unsigned)node->kind,
-			node->sized,
-			get<Type>().accept1( node->init )
-		);
-		cache.emplace( node, decl );
-		return namedTypePostamble( decl, node );
-	}
-
-	const ast::Decl * visit( const ast::TypedefDecl * node ) override final {
-		auto decl = new TypedefDecl(
-			node->name,
-			node->location,
-			Type::StorageClasses( node->storage.val ),
-			get<Type>().accept1( node->base ),
-			LinkageSpec::Spec( node->linkage.val )
-		);
-		return namedTypePostamble( decl, node );
-	}
-
-	const ast::Decl * aggregatePostamble( AggregateDecl * decl, const ast::AggregateDecl * node ) {
-		cache.emplace( node, decl );
-		decl->members = get<Declaration>().acceptL( node->members );
-		decl->parameters = get<TypeDecl>().acceptL( node->params );
-		decl->body = node->body;
-		// attributes come from constructor
-		decl->parent = get<AggregateDecl>().accept1( node->parent );
-		declPostamble( decl, node );
-		return nullptr; // ??
-	}
-
-	const ast::Decl * visit( const ast::StructDecl * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto decl = new StructDecl(
-			node->name,
-			(AggregateDecl::Aggregate)node->kind,
-			get<Attribute>().acceptL( node->attributes ),
-			LinkageSpec::Spec( node->linkage.val )
-		);
-
-		if ( ast::dtorStruct == node ) {
-			Validate::dtorStruct = decl;
-		}
-
-		return aggregatePostamble( decl, node );
-	}
-
-	const ast::Decl * visit( const ast::UnionDecl * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto decl = new UnionDecl(
-			node->name,
-			get<Attribute>().acceptL( node->attributes ),
-			LinkageSpec::Spec( node->linkage.val )
-		);
-		return aggregatePostamble( decl, node );
-	}
-
-	const ast::Decl * visit( const ast::EnumDecl * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto decl = new EnumDecl(
-			node->name,
-			get<Attribute>().acceptL( node->attributes ),
-			node->isTyped,
-			LinkageSpec::Spec( node->linkage.val ),
-			get<Type>().accept1(node->base)
-		);
-		return aggregatePostamble( decl, node );
-	}
-
-	const ast::Decl * visit( const ast::TraitDecl * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto decl = new TraitDecl(
-			node->name,
-			{},
-			LinkageSpec::Spec( node->linkage.val )
-		);
-		return aggregatePostamble( decl, node );
-	}
-
-	const ast::AsmDecl * visit( const ast::AsmDecl * node ) override final {
-		auto decl = new AsmDecl( get<AsmStmt>().accept1( node->stmt ) );
-		declPostamble( decl, node );
-		return nullptr;
-	}
-
-	const ast::DirectiveDecl * visit( const ast::DirectiveDecl * node ) override final {
-		auto decl = new DirectiveDecl( get<DirectiveStmt>().accept1( node->stmt ) );
-		declPostamble( decl, node );
-		return nullptr;
-	}
-
-	const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) override final {
-		auto decl = new StaticAssertDecl(
-			get<Expression>().accept1( node->cond ),
-			get<ConstantExpr>().accept1( node->msg )
-		);
-		declPostamble( decl, node );
-		return nullptr;
-	}
-
-	const ast::Stmt * stmtPostamble( Statement * stmt, const ast::Stmt * node ) {
-		// force statements in old tree to be unique.
-		// cache.emplace( node, stmt );
-		readonlyCache.emplace( node, stmt );
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
-	}
-
-	void clausePostamble( Statement * stmt, const ast::StmtClause * node ) {
-		stmt->location = node->location;
-		this->node = stmt;
-	}
-
-	const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new CompoundStmt( get<Statement>().acceptL( node->kids ) );
-		stmtPostamble( stmt, node );
-		return nullptr;
-	}
-
-	const ast::Stmt * visit( const ast::ExprStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new ExprStmt( nullptr );
-		stmt->expr = get<Expression>().accept1( node->expr );
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::AsmStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new AsmStmt(
-			node->isVolatile,
-			get<Expression>().accept1( node->instruction ),
-			get<Expression>().acceptL( node->output ),
-			get<Expression>().acceptL( node->input ),
-			get<ConstantExpr>().acceptL( node->clobber ),
-			makeLabelL( nullptr, node->gotoLabels ) // What are these labelling?
-		);
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::DirectiveStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new DirectiveStmt( node->directive );
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::IfStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new IfStmt(
-			get<Expression>().accept1( node->cond ),
-			get<Statement>().accept1( node->then ),
-			get<Statement>().accept1( node->else_ ),
-			get<Statement>().acceptL( node->inits )
-		);
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::SwitchStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new SwitchStmt(
-			get<Expression>().accept1( node->cond ),
-			get<Statement>().acceptL( node->cases )
-		);
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::CaseClause * visit( const ast::CaseClause * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new CaseStmt(
-			get<Expression>().accept1( node->cond ),
-			get<Statement>().acceptL( node->stmts ),
-			node->isDefault()
-		);
-		clausePostamble( stmt, node );
-		return nullptr;
-	}
-
-	const ast::Stmt * visit( const ast::WhileDoStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto inits = get<Statement>().acceptL( node->inits );
-		auto stmt = new WhileDoStmt(
-			get<Expression>().accept1( node->cond ),
-			get<Statement>().accept1( node->body ),
-			get<Statement>().accept1( node->else_ ),
-			inits,
-			node->isDoWhile
-		);
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::ForStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new ForStmt(
-			get<Statement>().acceptL( node->inits ),
-			get<Expression>().accept1( node->cond ),
-			get<Expression>().accept1( node->inc ),
-			get<Statement>().accept1( node->body ),
-			get<Statement>().accept1( node->else_ )
-		);
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::BranchStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		BranchStmt * stmt;
-		if (node->computedTarget) {
-			stmt = new BranchStmt( get<Expression>().accept1( node->computedTarget ),
-				BranchStmt::Goto );
-		} else {
-			BranchStmt::Type type;
-			switch (node->kind) {
-			#define CASE(n) \
-			case ast::BranchStmt::n: \
-				type = BranchStmt::n; \
-				break
-			CASE(Goto);
-			CASE(Break);
-			CASE(Continue);
-			CASE(FallThrough);
-			CASE(FallThroughDefault);
-			#undef CASE
-			default:
-				assertf(false, "Invalid ast::BranchStmt::Kind: %d\n", node->kind);
-			}
-
-			// The labels here are also weird.
-			stmt = new BranchStmt( makeLabel( nullptr, node->originalTarget ), type );
-			stmt->target = makeLabel( stmt, node->target );
-		}
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::ReturnStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new ReturnStmt( get<Expression>().accept1( node->expr ) );
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::ThrowStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		ThrowStmt::Kind kind;
-		switch (node->kind) {
-		case ast::ExceptionKind::Terminate:
-			kind = ThrowStmt::Terminate;
-			break;
-		case ast::ExceptionKind::Resume:
-			kind = ThrowStmt::Resume;
-			break;
-		default:
-			assertf(false, "Invalid ast::ThrowStmt::Kind: %d\n", node->kind);
-		}
-		auto stmt = new ThrowStmt(
-			kind,
-			get<Expression>().accept1( node->expr ),
-			get<Expression>().accept1( node->target )
-		);
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::TryStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto handlers = get<CatchStmt>().acceptL( node->handlers );
-		auto stmt = new TryStmt(
-			get<CompoundStmt>().accept1( node->body ),
-			handlers,
-			get<FinallyStmt>().accept1( node->finally )
-		);
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::CatchClause * visit( const ast::CatchClause * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		CatchStmt::Kind kind;
-		switch (node->kind) {
-		case ast::ExceptionKind::Terminate:
-			kind = CatchStmt::Terminate;
-			break;
-		case ast::ExceptionKind::Resume:
-			kind = CatchStmt::Resume;
-			break;
-		default:
-			assertf(false, "Invalid ast::ExceptionKind: %d\n", node->kind);
-		}
-		auto stmt = new CatchStmt(
-			kind,
-			get<Declaration>().accept1( node->decl ),
-			get<Expression>().accept1( node->cond ),
-			get<Statement>().accept1( node->body )
-		);
-		return clausePostamble( stmt, node ), nullptr;
-	}
-
-	const ast::FinallyClause * visit( const ast::FinallyClause * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new FinallyStmt( get<CompoundStmt>().accept1( node->body ) );
-		return clausePostamble( stmt, node ), nullptr;
-	}
-
-	const ast::Stmt * visit(const ast::SuspendStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new SuspendStmt();
-		stmt->then   = get<CompoundStmt>().accept1( node->then   );
-		switch (node->kind) {
-			case ast::SuspendStmt::None     : stmt->type = SuspendStmt::None     ; break;
-			case ast::SuspendStmt::Coroutine: stmt->type = SuspendStmt::Coroutine; break;
-			case ast::SuspendStmt::Generator: stmt->type = SuspendStmt::Generator; break;
-		}
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::WhenClause * visit( const ast::WhenClause * node ) override final {
-		// There is no old-AST WhenClause, so this should never be called.
-		assert( !node );
-		return nullptr;
-	}
-
-	const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new WaitForStmt;
-		stmt->clauses.reserve( node->clauses.size() );
-		for ( auto clause : node->clauses ) {
-			stmt->clauses.push_back({{
-					get<Expression>().accept1( clause->target ),
-					get<Expression>().acceptL( clause->target_args ),
-				},
-				get<Statement>().accept1( clause->stmt ),
-				get<Expression>().accept1( clause->when_cond ),
-			});
-		}
-		stmt->timeout = {
-			get<Expression>().accept1( node->timeout_time ),
-			get<Statement>().accept1( node->timeout_stmt ),
-			get<Expression>().accept1( node->timeout_cond ),
-		};
-		stmt->orelse = {
-			get<Statement>().accept1( node->else_stmt ),
-			get<Expression>().accept1( node->else_cond ),
-		};
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
-		// There is no old-AST WaitForClause, so this should never be called.
-		assert( !node );
-		return nullptr;
-	}
-
-	const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final {
-		// There is no old-AST WaitUntilStmt, so this should never be called.
-		assert( !node );
-		return nullptr;
-	}
-
-	const ast::Decl * visit( const ast::WithStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new WithStmt(
-			get<Expression>().acceptL( node->exprs ),
-			get<Statement>().accept1( node->stmt )
-		);
-		declPostamble( stmt, node );
-		return nullptr;
-	}
-
-	const ast::NullStmt * visit( const ast::NullStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new NullStmt();
-		stmtPostamble( stmt, node );
-		return nullptr;
-	}
-
-	const ast::Stmt * visit( const ast::DeclStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new DeclStmt( get<Declaration>().accept1( node->decl ) );
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		auto stmt = new ImplicitCtorDtorStmt{
-			get<Statement>().accept1( node->callStmt )
-		};
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::MutexStmt * node ) override final {
-		if ( inCache( node ) ) return nullptr;
-		 auto stmt = new MutexStmt(
-			get<Statement>().accept1( node->stmt ),
-		 	get<Expression>().acceptL( node->mutexObjs )
-		);
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::CorunStmt * node ) override final {
-		// There is no old-AST CorunStmt, so this should never be called.
-		assert( !node );
-		return nullptr;
-	}
-
-	const ast::Stmt * visit( const ast::CoforStmt * node ) override final {
-		// There is no old-AST CoforStmt, so this should never be called.
-		assert( !node );
-		return nullptr;
-	}
-
-	TypeSubstitution * convertTypeSubstitution(const ast::TypeSubstitution * src) {
-
-		if (!src) return nullptr;
-
-		TypeSubstitution *rslt = new TypeSubstitution();
-
-		for (decltype(src->begin()) src_i = src->begin(); src_i != src->end(); src_i++) {
-			rslt->add( src_i->first.typeString(),
-			           get<Type>().accept1(src_i->second) );
-		}
-
-		return rslt;
-	}
-
-	void convertInferUnion(std::map<UniqueId,ParamEntry> &tgtInferParams,
-						   std::vector<UniqueId>         &tgtResnSlots,
-						   const ast::Expr::InferUnion   &srcInferred ) {
-
-		assert( tgtInferParams.empty() );
-		assert( tgtResnSlots.empty() );
-
-		if ( srcInferred.data.inferParams ) {
-			const ast::InferredParams &srcParams = srcInferred.inferParams();
-			for (auto & srcParam : srcParams) {
-				auto res = tgtInferParams.emplace(srcParam.first, ParamEntry(
-					srcParam.second.decl,
-					get<Declaration>().accept1(srcParam.second.declptr),
-					get<Type>().accept1(srcParam.second.actualType)->clone(),
-					get<Type>().accept1(srcParam.second.formalType)->clone(),
-					get<Expression>().accept1(srcParam.second.expr)->clone()
-				));
-				assert(res.second);
-			}
-		}
-		if ( srcInferred.data.resnSlots ) {
-			const ast::ResnSlots &srcSlots = srcInferred.resnSlots();
-			for (auto srcSlot : srcSlots) {
-				tgtResnSlots.push_back(srcSlot);
-			}
-		}
-	}
-
-	Expression * visitBaseExpr_skipResultType(const ast::Expr * src, Expression * tgt) {
-
-		tgt->location  = src->location;
-		tgt->env       = convertTypeSubstitution(src->env);
-		tgt->extension = src->extension;
-
-		convertInferUnion(tgt->inferParams, tgt->resnSlots, src->inferred);
-		return tgt;
-	}
-
-	Expression * visitBaseExpr(const ast::Expr * src, Expression * tgt) {
-
-		tgt->result = get<Type>().accept1(src->result);
-		// Unconditionally use a clone of the result type.
-		// We know this will leak some objects: much of the immediate conversion result.
-		// In some cases, using the conversion result directly gives unintended object sharing.
-		// A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.
-		// But tgt->result must be fully owned privately by tgt.
-		// Applying these conservative copies here means
-		// - weak references point at the declaration's copy, not these expr.result copies (good)
-		// - we copy more objects than really needed (bad, tolerated)
-		if (tgt->result) {
-			tgt->result = tgt->result->clone();
-		}
-		return visitBaseExpr_skipResultType(src, tgt);
-	}
-
-	const ast::Expr * visit( const ast::ApplicationExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new ApplicationExpr(
-				get<Expression>().accept1(node->func),
-				get<Expression>().acceptL(node->args)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::UntypedExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new UntypedExpr(
-				get<Expression>().accept1(node->func),
-				get<Expression>().acceptL(node->args)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::NameExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new NameExpr(
-				node->name
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::QualifiedNameExpr * node ) override final {
-		auto temp = new QualifiedNameExpr(
-				get<Declaration>().accept1(node->type_decl),
-				node->name
-		);
-		auto expr = visitBaseExpr( node,
-			temp
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::AddressExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new AddressExpr(
-				get<Expression>().accept1(node->arg)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::LabelAddressExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new LabelAddressExpr(
-				makeLabel(nullptr, node->arg)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::CastExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new CastExpr(
-				get<Expression>().accept1(node->arg),
-				(node->isGenerated == ast::GeneratedCast)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::KeywordCastExpr * node ) override final {
-		AggregateDecl::Aggregate castTarget = (AggregateDecl::Aggregate)node->target;
-		assert( AggregateDecl::Generator <= castTarget && castTarget <= AggregateDecl::Thread );
-		auto expr = visitBaseExpr( node,
-			new KeywordCastExpr(
-				get<Expression>().accept1(node->arg),
-				castTarget,
-				{node->concrete_target.field, node->concrete_target.getter}
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::VirtualCastExpr * node ) override final {
-		auto expr = visitBaseExpr_skipResultType( node,
-			new VirtualCastExpr(
-				get<Expression>().accept1(node->arg),
-				get<Type>().accept1(node->result)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::UntypedMemberExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new UntypedMemberExpr(
-				get<Expression>().accept1(node->member),
-				get<Expression>().accept1(node->aggregate)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::MemberExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new MemberExpr(
-				get<DeclarationWithType>().accept1(node->member),
-				get<Expression>().accept1(node->aggregate)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::VariableExpr * node ) override final {
-		auto expr = new VariableExpr();
-		expr->var = get<DeclarationWithType>().accept1(node->var);
-		visitBaseExpr( node, expr );
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
-		// Old world:   two types: rslt->constant.type, rslt->result
-		// New workd:   one public type: node->result, plus node->underlyer only to support roundtrip conversion
-		//              preserving underlyer because the correct type for string literals is complicated to construct,
-		//              and distinguishing a string from other literals using the type is hard to do accurately
-		// Both worlds: the outer, expression-level type can change during resolution
-		//              for a string, that's char[k] before-resolve and char * after
-		// Old world:   the inner Constant type stays what it was built with
-		//              for a string, that's char[k] always
-		// Both worlds: the "rep" field of a constant is the C source file fragment that compiles to the desired value
-		//              for a string, that includes outer quotes, backslashes, et al cases from the Literals test
-		ConstantExpr *rslt = new ConstantExpr(Constant(
-			get<Type>().accept1(node->underlyer),
-			node->rep,
-			node->ival));
-		auto expr = visitBaseExpr( node, rslt );
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::SizeofExpr * node ) override final {
-		assert (node->expr || node->type);
-		assert (! (node->expr && node->type));
-		SizeofExpr *rslt;
-		if (node->expr) {
-			rslt = new SizeofExpr(
-				get<Expression>().accept1(node->expr)
-			);
-			assert (!rslt->isType);
-		}
-		else {
-			assert(node->type);
-			rslt = new SizeofExpr(
-				get<Type>().accept1(node->type)
-			);
-			assert (rslt->isType);
-		}
-		auto expr = visitBaseExpr( node, rslt );
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::AlignofExpr * node ) override final {
-		assert (node->expr || node->type);
-		assert (! (node->expr && node->type));
-		AlignofExpr *rslt;
-		if (node->expr) {
-			rslt = new AlignofExpr(
-				get<Expression>().accept1(node->expr)
-			);
-			assert (!rslt->isType);
-		}
-		else {
-			assert(node->type);
-			rslt = new AlignofExpr(
-				get<Type>().accept1(node->type)
-			);
-			assert (rslt->isType);
-		}
-		auto expr = visitBaseExpr( node, rslt );
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new UntypedOffsetofExpr(
-				get<Type>().accept1(node->type),
-				node->member
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::OffsetofExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new OffsetofExpr(
-				get<Type>().accept1(node->type),
-				get<DeclarationWithType>().accept1(node->member)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::OffsetPackExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new OffsetPackExpr(
-				get<StructInstType>().accept1(node->type)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::LogicalExpr * node ) override final {
-		assert (node->isAnd == ast::LogicalFlag::AndExpr ||
-				node->isAnd == ast::LogicalFlag::OrExpr	);
-		auto expr = visitBaseExpr( node,
-			new LogicalExpr(
-				get<Expression>().accept1(node->arg1),
-				get<Expression>().accept1(node->arg2),
-				(node->isAnd == ast::LogicalFlag::AndExpr)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::ConditionalExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new ConditionalExpr(
-				get<Expression>().accept1(node->arg1),
-				get<Expression>().accept1(node->arg2),
-				get<Expression>().accept1(node->arg3)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::CommaExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new CommaExpr(
-				get<Expression>().accept1(node->arg1),
-				get<Expression>().accept1(node->arg2)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::TypeExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new TypeExpr(
-				get<Type>().accept1(node->type)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::DimensionExpr * node ) override final {
-		auto expr = visitBaseExpr( node, new DimensionExpr( node->name ) );
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::AsmExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new AsmExpr(
-				new std::string(node->inout),
-				get<Expression>().accept1(node->constraint),
-				get<Expression>().accept1(node->operand)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) override final {
-		auto rslt = new ImplicitCopyCtorExpr(
-			get<ApplicationExpr>().accept1(node->callExpr)
-		);
-
-		auto expr = visitBaseExpr( node, rslt );
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::ConstructorExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new ConstructorExpr(
-				get<Expression>().accept1(node->callExpr)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) override final {
-		auto expr = visitBaseExpr_skipResultType( node,
-			new CompoundLiteralExpr(
-				get<Type>().accept1(node->result),
-				get<Initializer>().accept1(node->init)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::RangeExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new RangeExpr(
-				get<Expression>().accept1(node->low),
-				get<Expression>().accept1(node->high)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::UntypedTupleExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new UntypedTupleExpr(
-				get<Expression>().acceptL(node->exprs)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::TupleExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new TupleExpr(
-				get<Expression>().acceptL(node->exprs)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::TupleIndexExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new TupleIndexExpr(
-				get<Expression>().accept1(node->tuple),
-				node->index
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::TupleAssignExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new TupleAssignExpr(
-				get<StmtExpr>().accept1(node->stmtExpr)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::StmtExpr * node ) override final {
-		auto rslt = new StmtExpr(
-			get<CompoundStmt>().accept1(node->stmts)
-		);
-
-		rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
-		rslt->dtors       = get<Expression>().acceptL(node->dtors);
-
-		// is this even used after convert?
-		//if (tmp->resultExpr) {
-		//	// this MUST be found by children visit
-		//	rslt->resultExpr  = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(tmp->resultExpr));
-		//}
-
-		auto expr = visitBaseExpr( node, rslt );
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::UniqueExpr * node ) override final {
-		auto rslt = new UniqueExpr(
-			get<Expression>().accept1(node->expr),
-			node->id
-		);
-
-		rslt->object = get<ObjectDecl>  ().accept1(node->object);
-		rslt->var    = get<VariableExpr>().accept1(node->var);
-
-		auto expr = visitBaseExpr( node, rslt );
-		this->node = expr->clone();
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::UntypedInitExpr * node ) override final {
-		std::list<InitAlternative> initAlts;
-		for (auto ia : node->initAlts) {
-			initAlts.push_back(InitAlternative(
-				get<Type>       ().accept1(ia.type),
-				get<Designation>().accept1(ia.designation)
-			));
-		}
-		auto expr = visitBaseExpr( node,
-			new UntypedInitExpr(
-				get<Expression>().accept1(node->expr),
-				initAlts
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::InitExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new InitExpr(
-				get<Expression>().accept1(node->expr),
-				get<Designation>().accept1(node->designation)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::DeletedExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new DeletedExpr(
-				get<Expression>().accept1(node->expr),
-				inCache(node->deleteStmt) ?
-					strict_dynamic_cast<Declaration*>(this->node) :
-					get<Declaration>().accept1(node->deleteStmt)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::DefaultArgExpr * node ) override final {
-		auto expr = visitBaseExpr( node,
-			new DefaultArgExpr(
-				get<Expression>().accept1(node->expr)
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Expr * visit( const ast::GenericExpr * node ) override final {
-		std::list<GenericExpr::Association> associations;
-		for (auto association : node->associations) {
-			associations.push_back(GenericExpr::Association(
-				get<Type>      ().accept1(association.type),
-				get<Expression>().accept1(association.expr)
-			));
-		}
-		auto expr = visitBaseExpr( node,
-			new GenericExpr(
-				get<Expression>().accept1(node->control),
-				associations
-			)
-		);
-		this->node = expr;
-		return nullptr;
-	}
-
-	const ast::Type * visitType( const ast::Type * node, Type * type ) {
-		// Some types do this in their constructor so add a check.
-		if ( !node->attributes.empty() && type->attributes.empty() ) {
-			type->attributes = get<Attribute>().acceptL( node->attributes );
-		}
-		this->node = type;
-		return nullptr;
-	}
-
-	const ast::Type * visit( const ast::VoidType * node ) override final {
-		return visitType( node, new VoidType{ cv( node ) } );
-	}
-
-	const ast::Type * visit( const ast::BasicType * node ) override final {
-		auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind };
-		// I believe this should always be a BasicType.
-		if ( ast::sizeType == node ) {
-			Validate::SizeType = type;
-		}
-		return visitType( node, type );
-	}
-
-	const ast::Type * visit( const ast::PointerType * node ) override final {
-		return visitType( node, new PointerType{
-			cv( node ),
-			get<Type>().accept1( node->base ),
-			get<Expression>().accept1( node->dimension ),
-			(bool)node->isVarLen,
-			(bool)node->isStatic
-		} );
-	}
-
-	const ast::Type * visit( const ast::ArrayType * node ) override final {
-		return visitType( node, new ArrayType{
-			cv( node ),
-			get<Type>().accept1( node->base ),
-			get<Expression>().accept1( node->dimension ),
-			(bool)node->isVarLen,
-			(bool)node->isStatic
-		} );
-	}
-
-	const ast::Type * visit( const ast::ReferenceType * node ) override final {
-		return visitType( node, new ReferenceType{
-			cv( node ),
-			get<Type>().accept1( node->base )
-		} );
-	}
-
-	const ast::Type * visit( const ast::QualifiedType * node ) override final {
-		return visitType( node, new QualifiedType{
-			cv( node ),
-			get<Type>().accept1( node->parent ),
-			get<Type>().accept1( node->child )
-		} );
-	}
-
-	const ast::Type * visit( const ast::FunctionType * node ) override final {
-		static std::string dummy_paramvar_prefix = "__param_";
-		static std::string dummy_returnvar_prefix = "__retval_";
-
-		auto ty = new FunctionType {
-			cv( node ),
-			(bool)node->isVarArgs
-		};
-		auto returns = get<Type>().acceptL(node->returns);
-		auto params = get<Type>().acceptL(node->params);
-
-		int ret_index = 0;
-		for (auto t: returns) {
-			// xxx - LinkageSpec shouldn't matter but needs to be something
-			ObjectDecl * dummy = new ObjectDecl(dummy_returnvar_prefix + std::to_string(ret_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
-			ty->returnVals.push_back(dummy);
-		}
-		int param_index = 0;
-		for (auto t: params) {
-			ObjectDecl * dummy = new ObjectDecl(dummy_paramvar_prefix + std::to_string(param_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
-			ty->parameters.push_back(dummy);
-		}
-
-		// ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
-		// ty->parameters = get<DeclarationWithType>().acceptL( node->params );
-
-		auto types = get<TypeInstType>().acceptL( node->forall );
-		for (auto t : types) {
-			auto newT = new TypeDecl(*t->baseType);
-			newT->name = t->name; // converted by typeString()
-			for (auto asst : newT->assertions) delete asst;
-			newT->assertions.clear();
-			ty->forall.push_back(newT);
-		}
-		auto assts = get<VariableExpr>().acceptL( node->assertions );
-		if (!assts.empty()) {
-			assert(!types.empty());
-			for (auto asst : assts) {
-				auto newDecl = new ObjectDecl(*strict_dynamic_cast<ObjectDecl*>(asst->var));
-				delete newDecl->type;
-				newDecl->type = asst->result->clone();
-				newDecl->storageClasses.is_extern = true; // hack
-				ty->forall.back()->assertions.push_back(newDecl);
-			}
-		}
-
-		return visitType( node, ty );
-	}
-
-	const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) {
-		ty->parameters = get<Expression>().acceptL( old->params );
-		ty->hoistType = old->hoistType;
-		return visitType( old, ty );
-	}
-
-	const ast::Type * visit( const ast::StructInstType * node ) override final {
-		StructInstType * ty;
-		if ( node->base ) {
-			ty = new StructInstType{
-				cv( node ),
-				get<StructDecl>().accept1( node->base ),
-				get<Attribute>().acceptL( node->attributes )
-			};
-		} else {
-			ty = new StructInstType{
-				cv( node ),
-				node->name,
-				get<Attribute>().acceptL( node->attributes )
-			};
-		}
-		return postvisit( node, ty );
-	}
-
-	const ast::Type * visit( const ast::UnionInstType * node ) override final {
-		UnionInstType * ty;
-		if ( node->base ) {
-			ty = new UnionInstType{
-				cv( node ),
-				get<UnionDecl>().accept1( node->base ),
-				get<Attribute>().acceptL( node->attributes )
-			};
-		} else {
-			ty = new UnionInstType{
-				cv( node ),
-				node->name,
-				get<Attribute>().acceptL( node->attributes )
-			};
-		}
-		return postvisit( node, ty );
-	}
-
-	const ast::Type * visit( const ast::EnumInstType * node ) override final {
-		EnumInstType * ty;
-		if ( node->base ) {
-			ty = new EnumInstType{
-				cv( node ),
-				get<EnumDecl>().accept1( node->base ),
-				get<Attribute>().acceptL( node->attributes )
-			};
-		} else {
-			ty = new EnumInstType{
-				cv( node ),
-				node->name,
-				get<Attribute>().acceptL( node->attributes )
-			};
-		}
-		return postvisit( node, ty );
-	}
-
-	const ast::Type * visit( const ast::TraitInstType * node ) override final {
-		TraitInstType * ty;
-		if ( node->base ) {
-			ty = new TraitInstType{
-				cv( node ),
-				get<TraitDecl>().accept1( node->base ),
-				get<Attribute>().acceptL( node->attributes )
-			};
-		} else {
-			ty = new TraitInstType{
-				cv( node ),
-				node->name,
-				get<Attribute>().acceptL( node->attributes )
-			};
-		}
-		return postvisit( node, ty );
-	}
-
-	const ast::Type * visit( const ast::TypeInstType * node ) override final {
-		TypeInstType * ty;
-		if ( node->base ) {
-			ty = new TypeInstType{
-				cv( node ),
-				node->typeString(),
-				get<TypeDecl>().accept1( node->base ),
-				get<Attribute>().acceptL( node->attributes )
-			};
-		} else {
-			ty = new TypeInstType{
-				cv( node ),
-				node->typeString(),
-				node->kind == ast::TypeDecl::Ftype,
-				get<Attribute>().acceptL( node->attributes )
-			};
-		}
-		return postvisit( node, ty );
-	}
-
-	const ast::Type * visit( const ast::TupleType * node ) override final {
-		return visitType( node, new TupleType{
-			cv( node ),
-			get<Type>().acceptL( node->types )
-			// members generated by TupleType c'tor
-		} );
-	}
-
-	const ast::Type * visit( const ast::TypeofType * node ) override final {
-		return visitType( node, new TypeofType{
-			cv( node ),
-			get<Expression>().accept1( node->expr ),
-			(bool)node->kind
-		} );
-	}
-
-	const ast::Type * visit( const ast::VTableType * node ) override final {
-		return visitType( node, new VTableType{
-			cv( node ),
-			get<Type>().accept1( node->base )
-		} );
-	}
-
-	const ast::Type * visit( const ast::VarArgsType * node ) override final {
-		return visitType( node, new VarArgsType{ cv( node ) } );
-	}
-
-	const ast::Type * visit( const ast::ZeroType * node ) override final {
-		return visitType( node, new ZeroType{ cv( node ) } );
-	}
-
-	const ast::Type * visit( const ast::OneType * node ) override final {
-		return visitType( node, new OneType{ cv( node ) } );
-	}
-
-	const ast::Type * visit( const ast::GlobalScopeType * node ) override final {
-		return visitType( node, new GlobalScopeType{} );
-	}
-
-	const ast::Designation * visit( const ast::Designation * node ) override final {
-		auto designation = new Designation( get<Expression>().acceptL( node->designators ) );
-		designation->location = node->location;
-		this->node = designation;
-		return nullptr;
-	}
-
-	const ast::Init * visit( const ast::SingleInit * node ) override final {
-		auto init = new SingleInit(
-			get<Expression>().accept1( node->value ),
-			ast::MaybeConstruct == node->maybeConstructed
-		);
-		init->location = node->location;
-		this->node = init;
-		return nullptr;
-	}
-
-	const ast::Init * visit( const ast::ListInit * node ) override final {
-		auto init = new ListInit(
-			get<Initializer>().acceptL( node->initializers ),
-			get<Designation>().acceptL( node->designations ),
-			ast::MaybeConstruct == node->maybeConstructed
-		);
-		init->location = node->location;
-		this->node = init;
-		return nullptr;
-	}
-
-	const ast::Init * visit( const ast::ConstructorInit * node ) override final {
-		auto init = new ConstructorInit(
-			get<Statement>().accept1( node->ctor ),
-			get<Statement>().accept1( node->dtor ),
-			get<Initializer>().accept1( node->init )
-		);
-		init->location = node->location;
-		this->node = init;
-		return nullptr;
-	}
-
-	const ast::Attribute * visit( const ast::Attribute * node ) override final {
-		auto attr = new Attribute(
-			node->name,
-			get<Expression>().acceptL(node->params)
-		);
-		this->node = attr;
-		return nullptr;
-	}
-
-	const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) override final {
-		// Handled by convertTypeSubstitution helper instead.
-		// TypeSubstitution is not a node in the old model, so the conversion result wouldn't fit in this->node.
-		assert( 0 );
-		(void)node;
-		return nullptr;
-	}
-};
-
-std::list< Declaration * > convert( const ast::TranslationUnit && translationUnit ) {
-	// Copy values from the global store to the local static variables.
-	ast::sizeType = translationUnit.global.sizeType;
-	ast::dereferenceOperator = translationUnit.global.dereference;
-	ast::dtorStruct = translationUnit.global.dtorStruct;
-	ast::dtorStructDestroy = translationUnit.global.dtorDestroy;
-
-	ConverterNewToOld c;
-	std::list< Declaration * > decls;
-	for(auto d : translationUnit.decls) {
-		decls.emplace_back( c.decl( d ) );
-	}
-	return decls;
-}
-
-//================================================================================================
-
-class ConverterOldToNew : public Visitor {
-public:
-	ast::Decl * decl() {
-		return strict_dynamic_cast< ast::Decl * >( node );
-	}
-
-	ConverterOldToNew() = default;
-	ConverterOldToNew(const ConverterOldToNew &) = delete;
-	ConverterOldToNew(ConverterOldToNew &&) = delete;
-private:
-	/// conversion output
-	ast::Node * node = nullptr;
-	/// cache of nodes that might be referenced by readonly<> for de-duplication
-	/// in case that some nodes are dropped by conversion (due to possible structural change)
-	/// use smart pointers in cache value to prevent accidental invalidation.
-	/// at conversion stage, all created nodes are guaranteed to be unique, therefore
-	/// const_casting out of smart pointers is permitted.
-	std::unordered_map< const BaseSyntaxNode *, ast::readonly<ast::Node> > cache = {};
-
-	// Local Utilities:
-
-	template<typename NewT, typename OldT>
-	NewT * getAccept1( OldT old ) {
-		if ( ! old ) return nullptr;
-		old->accept(*this);
-		ast::Node * ret = node;
-		node = nullptr;
-		return strict_dynamic_cast< NewT * >( ret );
-	}
-
-#	define GET_ACCEPT_1(child, type) \
-		getAccept1< ast::type, decltype( old->child ) >( old->child )
-
-
-	template<typename NewT, typename OldC>
-	std::vector< ast::ptr<NewT> > getAcceptV( const OldC& old ) {
-		std::vector< ast::ptr<NewT> > ret;
-		ret.reserve( old.size() );
-		for ( auto a : old ) {
-			a->accept( *this );
-			ret.emplace_back( strict_dynamic_cast< NewT * >(node) );
-			node = nullptr;
-		}
-		return ret;
-	}
-
-#	define GET_ACCEPT_V(child, type) \
-		getAcceptV< ast::type, decltype( old->child ) >( old->child )
-
-#	define GET_ACCEPT_E(child, type) \
-		getAccept1< ast::type, decltype( old->base ) >( old->base )
-
-	template<typename NewT, typename OldC>
-	std::deque< ast::ptr<NewT> > getAcceptD( const OldC& old ) {
-		std::deque< ast::ptr<NewT> > ret;
-		for ( auto a : old ) {
-			a->accept( *this );
-			ret.emplace_back( strict_dynamic_cast< NewT * >(node) );
-			node = nullptr;
-		}
-		return ret;
-	}
-
-#	define GET_ACCEPT_D(child, type) \
-		getAcceptD< ast::type, decltype( old->child ) >( old->child )
-
-	ast::Label make_label(const Label* old) {
-		CodeLocation const & location =
-			( old->labelled ) ? old->labelled->location : CodeLocation();
-		return ast::Label(
-			location,
-			old->name,
-			GET_ACCEPT_V(attributes, Attribute)
-		);
-	}
-
-	template<template <class...> class C>
-	C<ast::Label> make_labels(C<Label> olds) {
-		C<ast::Label> ret;
-		for (auto oldn : olds) {
-			ret.push_back( make_label( &oldn ) );
-		}
-		return ret;
-	}
-
-#	define GET_LABELS_V(labels) \
-		to<std::vector>::from( make_labels( std::move( labels ) ) )
-
-	static ast::CV::Qualifiers cv( const Type * ty ) { return { ty->tq.val }; }
-
-	/// returns true and sets `node` if in cache
-	bool inCache( const BaseSyntaxNode * old ) {
-		auto it = cache.find( old );
-		if ( it == cache.end() ) return false;
-		node = const_cast<ast::Node *>(it->second.get());
-		return true;
-	}
-
-	// Now all the visit functions:
-
-	virtual void visit( const ObjectDecl * old ) override final {
-		if ( inCache( old ) ) {
-			return;
-		}
-		auto&& type = GET_ACCEPT_1(type, Type);
-		auto&& init = GET_ACCEPT_1(init, Init);
-		auto&& bfwd = GET_ACCEPT_1(bitfieldWidth, Expr);
-		auto&& attr = GET_ACCEPT_V(attributes, Attribute);
-
-		auto decl = new ast::ObjectDecl(
-			old->location,
-			old->name,
-			type,
-			init,
-			{ old->get_storageClasses().val },
-			{ old->linkage.val },
-			bfwd,
-			std::move(attr),
-			{ old->get_funcSpec().val }
-		);
-		cache.emplace(old, decl);
-		assert(cache.find( old ) != cache.end());
-		decl->scopeLevel = old->scopeLevel;
-		decl->mangleName = old->mangleName;
-		decl->isDeleted  = old->isDeleted;
-		decl->asmName    = GET_ACCEPT_1(asmName, Expr);
-		decl->uniqueId   = old->uniqueId;
-		decl->extension  = old->extension;
-
-		this->node = decl;
-	}
-
-	virtual void visit( const FunctionDecl * old ) override final {
-		if ( inCache( old ) ) return;
-		auto paramVars = GET_ACCEPT_V(type->parameters, DeclWithType);
-		auto returnVars = GET_ACCEPT_V(type->returnVals, DeclWithType);
-		auto forall = GET_ACCEPT_V(type->forall, TypeDecl);
-
-		// function type is now derived from parameter decls instead of storing them
-
-		/*
-		auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type));
-		ftype->params.reserve(paramVars.size());
-		ftype->returns.reserve(returnVars.size());
-
-		for (auto & v: paramVars) {
-			ftype->params.emplace_back(v->get_type());
-		}
-		for (auto & v: returnVars) {
-			ftype->returns.emplace_back(v->get_type());
-		}
-		ftype->forall = std::move(forall);
-		*/
-
-		// can function type have attributes? seems not to be the case.
-		// visitType(old->type, ftype);
-
-		// collect assertions and put directly in FunctionDecl
-		std::vector<ast::ptr<ast::DeclWithType>> assertions;
-		for (auto & param: forall) {
-			for (auto & asst: param->assertions) {
-				assertf(asst->unique(), "newly converted decl must be unique");
-				assertions.emplace_back(asst);
-			}
-			auto mut = param.get_and_mutate();
-			assertf(mut == param, "newly converted decl must be unique");
-			mut->assertions.clear();
-		}
-
-		auto decl = new ast::FunctionDecl{
-			old->location,
-			old->name,
-			// GET_ACCEPT_1(type, FunctionType),
-			std::move(forall),
-			std::move(assertions),
-			std::move(paramVars),
-			std::move(returnVars),
-			{},
-			{ old->storageClasses.val },
-			{ old->linkage.val },
-			GET_ACCEPT_V(attributes, Attribute),
-			{ old->get_funcSpec().val },
-			(old->type->isVarArgs) ? ast::VariableArgs : ast::FixedArgs
-		};
-
-		// decl->type = ftype;
-		cache.emplace( old, decl );
-
-		decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
-		decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
-		decl->scopeLevel = old->scopeLevel;
-		decl->mangleName = old->mangleName;
-		decl->isDeleted  = old->isDeleted;
-		decl->asmName    = GET_ACCEPT_1(asmName, Expr);
-		decl->uniqueId   = old->uniqueId;
-		decl->extension  = old->extension;
-
-		this->node = decl;
-
-		if ( Validate::dereferenceOperator == old ) {
-			ast::dereferenceOperator = decl;
-		}
-
-		if ( Validate::dtorStructDestroy == old ) {
-			ast::dtorStructDestroy = decl;
-		}
-	}
-
-	virtual void visit( const StructDecl * old ) override final {
-		if ( inCache( old ) ) return;
-		auto decl = new ast::StructDecl(
-			old->location,
-			old->name,
-			(ast::AggregateDecl::Aggregate)old->kind,
-			GET_ACCEPT_V(attributes, Attribute),
-			{ old->linkage.val }
-		);
-		cache.emplace( old, decl );
-		decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
-		decl->body   = old->body;
-		decl->params = GET_ACCEPT_V(parameters, TypeDecl);
-		decl->members    = GET_ACCEPT_V(members, Decl);
-		decl->extension  = old->extension;
-		decl->uniqueId   = old->uniqueId;
-		decl->storage    = { old->storageClasses.val };
-
-		this->node = decl;
-
-		if ( Validate::dtorStruct == old ) {
-			ast::dtorStruct = decl;
-		}
-	}
-
-	virtual void visit( const UnionDecl * old ) override final {
-		if ( inCache( old ) ) return;
-		auto decl = new ast::UnionDecl(
-			old->location,
-			old->name,
-			GET_ACCEPT_V(attributes, Attribute),
-			{ old->linkage.val }
-		);
-		cache.emplace( old, decl );
-		decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
-		decl->body   = old->body;
-		decl->params = GET_ACCEPT_V(parameters, TypeDecl);
-		decl->members    = GET_ACCEPT_V(members, Decl);
-		decl->extension  = old->extension;
-		decl->uniqueId   = old->uniqueId;
-		decl->storage    = { old->storageClasses.val };
-
-		this->node = decl;
-	}
-
-
-	virtual void visit( const EnumDecl * old ) override final {
-		if ( inCache( old ) ) return;
-		auto decl = new ast::EnumDecl(
-			old->location,
-			old->name,
-			old->isTyped,
-			GET_ACCEPT_V(attributes, Attribute),
-			{ old->linkage.val },
-			GET_ACCEPT_1(base, Type),
-			old->hide == EnumDecl::EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible,
-			old->enumValues
-		);
-		cache.emplace( old, decl );
-		decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
-		decl->body   = old->body;
-		decl->params = GET_ACCEPT_V(parameters, TypeDecl);
-		decl->members    = GET_ACCEPT_V(members, Decl);
-		decl->extension  = old->extension;
-		decl->uniqueId   = old->uniqueId;
-		decl->storage    = { old->storageClasses.val };
-		this->node = decl;
-	}
-
-	virtual void visit( const TraitDecl * old ) override final {
-		if ( inCache( old ) ) return;
-		auto decl = new ast::TraitDecl(
-			old->location,
-			old->name,
-			GET_ACCEPT_V(attributes, Attribute),
-			{ old->linkage.val }
-		);
-		cache.emplace( old, decl );
-		decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
-		decl->body   = old->body;
-		decl->params = GET_ACCEPT_V(parameters, TypeDecl);
-		decl->members    = GET_ACCEPT_V(members, Decl);
-		decl->extension  = old->extension;
-		decl->uniqueId   = old->uniqueId;
-		decl->storage    = { old->storageClasses.val };
-
-		this->node = decl;
-	}
-
-	virtual void visit( const TypeDecl * old ) override final {
-		if ( inCache( old ) ) return;
-		auto decl = new ast::TypeDecl{
-			old->location,
-			old->name,
-			{ old->storageClasses.val },
-			GET_ACCEPT_1(base, Type),
-			(ast::TypeDecl::Kind)(unsigned)old->kind,
-			old->sized,
-			GET_ACCEPT_1(init, Type)
-		};
-		cache.emplace( old, decl );
-		decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
-		decl->extension  = old->extension;
-		decl->uniqueId   = old->uniqueId;
-
-		this->node = decl;
-	}
-
-	virtual void visit( const TypedefDecl * old ) override final {
-		auto decl = new ast::TypedefDecl(
-			old->location,
-			old->name,
-			{ old->storageClasses.val },
-			GET_ACCEPT_1(base, Type),
-			{ old->linkage.val }
-		);
-		decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
-		decl->extension  = old->extension;
-		decl->uniqueId   = old->uniqueId;
-		decl->storage    = { old->storageClasses.val };
-
-		this->node = decl;
-	}
-
-	virtual void visit( const AsmDecl * old ) override final {
-		auto decl = new ast::AsmDecl{
-			old->location,
-			GET_ACCEPT_1(stmt, AsmStmt)
-		};
-		decl->extension  = old->extension;
-		decl->uniqueId   = old->uniqueId;
-		decl->storage    = { old->storageClasses.val };
-
-		this->node = decl;
-	}
-
-	virtual void visit( const DirectiveDecl * old ) override final {
-		auto decl = new ast::DirectiveDecl{
-			old->location,
-			GET_ACCEPT_1(stmt, DirectiveStmt)
-		};
-		decl->extension  = old->extension;
-		decl->uniqueId   = old->uniqueId;
-		decl->storage    = { old->storageClasses.val };
-
-		this->node = decl;
-	}
-
-	virtual void visit( const StaticAssertDecl * old ) override final {
-		auto decl = new ast::StaticAssertDecl{
-			old->location,
-			GET_ACCEPT_1(condition, Expr),
-			GET_ACCEPT_1(message, ConstantExpr)
-		};
-		decl->extension  = old->extension;
-		decl->uniqueId   = old->uniqueId;
-		decl->storage    = { old->storageClasses.val };
-
-		this->node = decl;
-	}
-
-	virtual void visit( const InlineMemberDecl * old ) override final {
-		if ( inCache( old ) ) {
-			return;
-		}
-		auto&& type = GET_ACCEPT_1(type, Type);
-		auto&& attr = GET_ACCEPT_V(attributes, Attribute);
-
-		auto decl = new ast::InlineMemberDecl(
-			old->location,
-			old->name,
-			type,
-			{ old->get_storageClasses().val },
-			{ old->linkage.val },
-			std::move(attr),
-			{ old->get_funcSpec().val }
-		);
-		cache.emplace(old, decl);
-		assert(cache.find( old ) != cache.end());
-		decl->scopeLevel = old->scopeLevel;
-		decl->mangleName = old->mangleName;
-		decl->isDeleted  = old->isDeleted;
-		decl->asmName    = GET_ACCEPT_1(asmName, Expr);
-		decl->uniqueId   = old->uniqueId;
-		decl->extension  = old->extension;
-
-		this->node = decl;
-	}
-
-	virtual void visit( const CompoundStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		auto stmt = new ast::CompoundStmt(
-			old->location,
-			to<std::list>::from( GET_ACCEPT_V(kids, Stmt) ),
-			GET_LABELS_V(old->labels)
-		);
-
-		this->node = stmt;
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const ExprStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::ExprStmt(
-			old->location,
-			GET_ACCEPT_1(expr, Expr),
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const AsmStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::AsmStmt(
-			old->location,
-			old->voltile,
-			GET_ACCEPT_1(instruction, Expr),
-			GET_ACCEPT_V(output, Expr),
-			GET_ACCEPT_V(input, Expr),
-			GET_ACCEPT_V(clobber, ConstantExpr),
-			GET_LABELS_V(old->gotolabels),
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const DirectiveStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::DirectiveStmt(
-			old->location,
-			old->directive,
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const IfStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::IfStmt(
-			old->location,
-			GET_ACCEPT_1(condition, Expr),
-			GET_ACCEPT_1(then, Stmt),
-			GET_ACCEPT_1(else_, Stmt),
-			GET_ACCEPT_V(initialization, Stmt),
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const SwitchStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::SwitchStmt(
-			old->location,
-			GET_ACCEPT_1(condition, Expr),
-			GET_ACCEPT_V(statements, CaseClause),
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const CaseStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::CaseClause(
-			old->location,
-			GET_ACCEPT_1(condition, Expr),
-			GET_ACCEPT_V(stmts, Stmt)
-		);
-		auto labels = GET_LABELS_V(old->labels);
-		assertf(labels.empty(), "Labels found on CaseStmt.");
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const WhileDoStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::WhileDoStmt(
-			old->location,
-			GET_ACCEPT_1(condition, Expr),
-			GET_ACCEPT_1(body, Stmt),
-			GET_ACCEPT_1(else_, Stmt),
-			GET_ACCEPT_V(initialization, Stmt),
-			(old->isDoWhile) ? ast::DoWhile : ast::While,
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const ForStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::ForStmt(
-			old->location,
-			GET_ACCEPT_V(initialization, Stmt),
-			GET_ACCEPT_1(condition, Expr),
-			GET_ACCEPT_1(increment, Expr),
-			GET_ACCEPT_1(body, Stmt),
-			GET_ACCEPT_1(else_, Stmt),
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const BranchStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		if (old->computedTarget) {
-			this->node = new ast::BranchStmt(
-				old->location,
-				GET_ACCEPT_1(computedTarget, Expr),
-				GET_LABELS_V(old->labels)
-			);
-		} else {
-			ast::BranchStmt::Kind kind;
-			switch (old->type) {
-			#define CASE(n) \
-			case BranchStmt::n: \
-				kind = ast::BranchStmt::n; \
-				break
-			CASE(Goto);
-			CASE(Break);
-			CASE(Continue);
-			CASE(FallThrough);
-			CASE(FallThroughDefault);
-			#undef CASE
-			default:
-				assertf(false, "Invalid BranchStmt::Type %d\n", old->type);
-			}
-
-			auto stmt = new ast::BranchStmt(
-				old->location,
-				kind,
-				make_label(&old->originalTarget),
-				GET_LABELS_V(old->labels)
-			);
-			stmt->target = make_label(&old->target);
-			this->node = stmt;
-		}
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const ReturnStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::ReturnStmt(
-			old->location,
-			GET_ACCEPT_1(expr, Expr),
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const ThrowStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		ast::ExceptionKind kind;
-		switch (old->kind) {
-		case ThrowStmt::Terminate:
-			kind = ast::ExceptionKind::Terminate;
-			break;
-		case ThrowStmt::Resume:
-			kind = ast::ExceptionKind::Resume;
-			break;
-		default:
-			assertf(false, "Invalid ThrowStmt::Kind %d\n", old->kind);
-		}
-
-		this->node = new ast::ThrowStmt(
-			old->location,
-			kind,
-			GET_ACCEPT_1(expr, Expr),
-			GET_ACCEPT_1(target, Expr),
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const TryStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::TryStmt(
-			old->location,
-			GET_ACCEPT_1(block, CompoundStmt),
-			GET_ACCEPT_V(handlers, CatchClause),
-			GET_ACCEPT_1(finallyBlock, FinallyClause),
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const CatchStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		ast::ExceptionKind kind;
-		switch (old->kind) {
-		case CatchStmt::Terminate:
-			kind = ast::ExceptionKind::Terminate;
-			break;
-		case CatchStmt::Resume:
-			kind = ast::ExceptionKind::Resume;
-			break;
-		default:
-			assertf(false, "Invalid CatchStmt::Kind %d\n", old->kind);
-		}
-
-		this->node = new ast::CatchClause(
-			old->location,
-			kind,
-			GET_ACCEPT_1(decl, Decl),
-			GET_ACCEPT_1(cond, Expr),
-			GET_ACCEPT_1(body, Stmt)
-		);
-		auto labels = GET_LABELS_V(old->labels);
-		assertf(labels.empty(), "Labels found on CatchStmt.");
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const FinallyStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::FinallyClause(
-			old->location,
-			GET_ACCEPT_1(block, CompoundStmt)
-		);
-		auto labels = GET_LABELS_V(old->labels);
-		assertf(labels.empty(), "Labels found on FinallyStmt.");
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const SuspendStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		ast::SuspendStmt::Kind type;
-		switch (old->type) {
-			case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break;
-			case SuspendStmt::Generator: type = ast::SuspendStmt::Generator; break;
-			case SuspendStmt::None     : type = ast::SuspendStmt::None     ; break;
-			default: abort();
-		}
-		this->node = new ast::SuspendStmt(
-			old->location,
-			GET_ACCEPT_1(then  , CompoundStmt),
-			type,
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const WaitForStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		ast::WaitForStmt * stmt = new ast::WaitForStmt(
-			old->location,
-			GET_LABELS_V(old->labels)
-		);
-
-		stmt->clauses.reserve( old->clauses.size() );
-		for (size_t i = 0 ; i < old->clauses.size() ; ++i) {
-			auto clause = new ast::WaitForClause( old->location );
-
-			clause->target = GET_ACCEPT_1(clauses[i].target.function, Expr);
-			clause->target_args = GET_ACCEPT_V(clauses[i].target.arguments, Expr);
-			clause->stmt = GET_ACCEPT_1(clauses[i].statement, Stmt);
-			clause->when_cond = GET_ACCEPT_1(clauses[i].condition, Expr);
-
-			stmt->clauses.push_back( clause );
-		}
-		stmt->timeout_time = GET_ACCEPT_1(timeout.time, Expr);
-		stmt->timeout_stmt = GET_ACCEPT_1(timeout.statement, Stmt);
-		stmt->timeout_cond = GET_ACCEPT_1(timeout.condition, Expr);
-		stmt->else_stmt = GET_ACCEPT_1(orelse.statement, Stmt);
-		stmt->else_cond = GET_ACCEPT_1(orelse.condition, Expr);
-
-		this->node = stmt;
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const WithStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::WithStmt(
-			old->location,
-			GET_ACCEPT_V(exprs, Expr),
-			GET_ACCEPT_1(stmt, Stmt)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const NullStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::NullStmt(
-			old->location,
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const DeclStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::DeclStmt(
-			old->location,
-			GET_ACCEPT_1(decl, Decl),
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	virtual void visit( const ImplicitCtorDtorStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		auto stmt = new ast::ImplicitCtorDtorStmt(
-			old->location,
-			nullptr,
-			GET_LABELS_V(old->labels)
-		);
-		cache.emplace( old, stmt );
-		stmt->callStmt = GET_ACCEPT_1(callStmt, Stmt);
-		this->node = stmt;
-	}
-
-	virtual void visit( const MutexStmt * old ) override final {
-		if ( inCache( old ) ) return;
-		this->node = new ast::MutexStmt(
-			old->location,
-			GET_ACCEPT_1(stmt, Stmt),
-			GET_ACCEPT_V(mutexObjs, Expr)
-		);
-		cache.emplace( old, this->node );
-	}
-
-	// TypeSubstitution shouldn't exist yet in old.
-	ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) {
-		if (!old) return nullptr;
-		if (old->empty()) return nullptr;
-		assert(false);
-
-		/*
-		ast::TypeSubstitution *rslt = new ast::TypeSubstitution();
-
-		for (decltype(old->begin()) old_i = old->begin(); old_i != old->end(); old_i++) {
-			rslt->add( old_i->first,
-			           getAccept1<ast::Type>(old_i->second) );
-		}
-
-		return rslt;
-		*/
-	}
-
-	void convertInferUnion(ast::Expr::InferUnion               &newInferred,
-						   const std::map<UniqueId,ParamEntry> &oldInferParams,
-						   const std::vector<UniqueId>         &oldResnSlots) {
-
-		assert( oldInferParams.empty() || oldResnSlots.empty() );
-		// assert( newInferred.mode == ast::Expr::InferUnion::Empty );
-
-		if ( !oldInferParams.empty() ) {
-			ast::InferredParams &tgt = newInferred.inferParams();
-			for (auto & old : oldInferParams) {
-				tgt[old.first] = ast::ParamEntry(
-					old.second.decl,
-					getAccept1<ast::Decl>(old.second.declptr),
-					getAccept1<ast::Type>(old.second.actualType),
-					getAccept1<ast::Type>(old.second.formalType),
-					getAccept1<ast::Expr>(old.second.expr)
-				);
-			}
-		} else if ( !oldResnSlots.empty() ) {
-			ast::ResnSlots &tgt = newInferred.resnSlots();
-			for (auto old : oldResnSlots) {
-				tgt.push_back(old);
-			}
-		}
-	}
-
-	ast::Expr * visitBaseExpr_SkipResultType( const Expression * old, ast::Expr * nw) {
-
-		nw->env = convertTypeSubstitution(old->env);
-
-		nw->extension = old->extension;
-		convertInferUnion(nw->inferred, old->inferParams, old->resnSlots);
-
-		return nw;
-	}
-
-	ast::Expr * visitBaseExpr( const Expression * old, ast::Expr * nw) {
-
-		nw->result = GET_ACCEPT_1(result, Type);
-		return visitBaseExpr_SkipResultType(old, nw);;
-	}
-
-	virtual void visit( const ApplicationExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::ApplicationExpr(
-				old->location,
-				GET_ACCEPT_1(function, Expr),
-				GET_ACCEPT_V(args, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const UntypedExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::UntypedExpr(
-				old->location,
-				GET_ACCEPT_1(function, Expr),
-				GET_ACCEPT_V(args, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const NameExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::NameExpr(
-				old->location,
-				old->get_name()
-			)
-		);
-	}
-
-	virtual void visit( const QualifiedNameExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::QualifiedNameExpr (
-				old->location,
-				GET_ACCEPT_1(type_decl, Decl),
-				old->name
-			)
-		);
-	}
-
-	virtual void visit( const CastExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::CastExpr(
-				old->location,
-				GET_ACCEPT_1(arg, Expr),
-				old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast,
-				(ast::CastExpr::CastKind) old->kind
-			)
-		);
-	}
-
-	virtual void visit( const KeywordCastExpr * old ) override final {
-		ast::AggregateDecl::Aggregate castTarget = (ast::AggregateDecl::Aggregate)old->target;
-		assert( ast::AggregateDecl::Generator <= castTarget && castTarget <= ast::AggregateDecl::Thread );
-		this->node = visitBaseExpr( old,
-			new ast::KeywordCastExpr(
-				old->location,
-				GET_ACCEPT_1(arg, Expr),
-				castTarget,
-				{old->concrete_target.field, old->concrete_target.getter}
-			)
-		);
-	}
-
-	virtual void visit( const VirtualCastExpr * old ) override final {
-		this->node = visitBaseExpr_SkipResultType( old,
-			new ast::VirtualCastExpr(
-				old->location,
-				GET_ACCEPT_1(arg, Expr),
-				GET_ACCEPT_1(result, Type)
-			)
-		);
-	}
-
-	virtual void visit( const AddressExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::AddressExpr(
-				old->location,
-				GET_ACCEPT_1(arg, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const LabelAddressExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::LabelAddressExpr(
-				old->location,
-				make_label(&old->arg)
-			)
-		);
-	}
-
-	virtual void visit( const UntypedMemberExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::UntypedMemberExpr(
-				old->location,
-				GET_ACCEPT_1(member, Expr),
-				GET_ACCEPT_1(aggregate, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const MemberExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::MemberExpr(
-				old->location,
-				GET_ACCEPT_1(member, DeclWithType),
-				GET_ACCEPT_1(aggregate, Expr),
-				ast::MemberExpr::NoOpConstructionChosen
-			)
-		);
-	}
-
-	virtual void visit( const VariableExpr * old ) override final {
-		auto expr = new ast::VariableExpr(
-			old->location
-		);
-
-		expr->var = GET_ACCEPT_1(var, DeclWithType);
-		visitBaseExpr( old, expr );
-
-		this->node = expr;
-	}
-
-	virtual void visit( const ConstantExpr * old ) override final {
-		ast::ConstantExpr *rslt = new ast::ConstantExpr(
-			old->location,
-			GET_ACCEPT_1(result, Type),
-			old->constant.rep,
-			old->constant.ival
-		);
-		rslt->underlyer = getAccept1< ast::Type, Type* >( old->constant.type );
-		this->node = visitBaseExpr( old, rslt );
-	}
-
-	virtual void visit( const SizeofExpr * old ) override final {
-		assert (old->expr || old->type);
-		assert (! (old->expr && old->type));
-		ast::SizeofExpr *rslt;
-		if (old->expr) {
-			assert(!old->isType);
-			rslt = new ast::SizeofExpr(
-				old->location,
-				GET_ACCEPT_1(expr, Expr)
-			);
-		}
-		if (old->type) {
-			assert(old->isType);
-			rslt = new ast::SizeofExpr(
-				old->location,
-				GET_ACCEPT_1(type, Type)
-			);
-		}
-		this->node = visitBaseExpr( old, rslt );
-	}
-
-	virtual void visit( const AlignofExpr * old ) override final {
-		assert (old->expr || old->type);
-		assert (! (old->expr && old->type));
-		ast::AlignofExpr *rslt;
-		if (old->expr) {
-			assert(!old->isType);
-			rslt = new ast::AlignofExpr(
-				old->location,
-				GET_ACCEPT_1(expr, Expr)
-			);
-		}
-		if (old->type) {
-			assert(old->isType);
-			rslt = new ast::AlignofExpr(
-				old->location,
-				GET_ACCEPT_1(type, Type)
-			);
-		}
-		this->node = visitBaseExpr( old, rslt );
-	}
-
-	virtual void visit( const UntypedOffsetofExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::UntypedOffsetofExpr(
-				old->location,
-				GET_ACCEPT_1(type, Type),
-				old->member
-			)
-		);
-	}
-
-	virtual void visit( const OffsetofExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::OffsetofExpr(
-				old->location,
-				GET_ACCEPT_1(type, Type),
-				GET_ACCEPT_1(member, DeclWithType)
-			)
-		);
-	}
-
-	virtual void visit( const OffsetPackExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::OffsetPackExpr(
-				old->location,
-				GET_ACCEPT_1(type, StructInstType)
-			)
-		);
-	}
-
-	virtual void visit( const LogicalExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::LogicalExpr(
-				old->location,
-				GET_ACCEPT_1(arg1, Expr),
-				GET_ACCEPT_1(arg2, Expr),
-				old->get_isAnd() ?
-					ast::LogicalFlag::AndExpr :
-					ast::LogicalFlag::OrExpr
-			)
-		);
-	}
-
-	virtual void visit( const ConditionalExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::ConditionalExpr(
-				old->location,
-				GET_ACCEPT_1(arg1, Expr),
-				GET_ACCEPT_1(arg2, Expr),
-				GET_ACCEPT_1(arg3, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const CommaExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::CommaExpr(
-				old->location,
-				GET_ACCEPT_1(arg1, Expr),
-				GET_ACCEPT_1(arg2, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const TypeExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::TypeExpr(
-				old->location,
-				GET_ACCEPT_1(type, Type)
-			)
-		);
-	}
-
-	virtual void visit( const DimensionExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::DimensionExpr( old->location, old->name )
-		);
-	}
-
-	virtual void visit( const AsmExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::AsmExpr(
-				old->location,
-				old->inout,
-				GET_ACCEPT_1(constraint, Expr),
-				GET_ACCEPT_1(operand, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const ImplicitCopyCtorExpr * old ) override final {
-		auto rslt = new ast::ImplicitCopyCtorExpr(
-			old->location,
-			GET_ACCEPT_1(callExpr, ApplicationExpr)
-		);
-
-		this->node = visitBaseExpr( old, rslt );
-	}
-
-	virtual void visit( const ConstructorExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::ConstructorExpr(
-				old->location,
-				GET_ACCEPT_1(callExpr, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const CompoundLiteralExpr * old ) override final {
-		this->node = visitBaseExpr_SkipResultType( old,
-			new ast::CompoundLiteralExpr(
-				old->location,
-				GET_ACCEPT_1(result, Type),
-				GET_ACCEPT_1(initializer, Init)
-			)
-		);
-	}
-
-	virtual void visit( const RangeExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::RangeExpr(
-				old->location,
-				GET_ACCEPT_1(low, Expr),
-				GET_ACCEPT_1(high, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const UntypedTupleExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::UntypedTupleExpr(
-				old->location,
-				GET_ACCEPT_V(exprs, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const TupleExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::TupleExpr(
-				old->location,
-				GET_ACCEPT_V(exprs, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const TupleIndexExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::TupleIndexExpr(
-				old->location,
-				GET_ACCEPT_1(tuple, Expr),
-				old->index
-			)
-		);
-	}
-
-	virtual void visit( const TupleAssignExpr * old ) override final {
-		this->node = visitBaseExpr_SkipResultType( old,
-			new ast::TupleAssignExpr(
-				old->location,
-				GET_ACCEPT_1(result, Type),
-				GET_ACCEPT_1(stmtExpr, StmtExpr)
-			)
-		);
-	}
-
-	virtual void visit( const StmtExpr * old ) override final {
-		auto rslt = new ast::StmtExpr(
-			old->location,
-			GET_ACCEPT_1(statements, CompoundStmt)
-		);
-		rslt->returnDecls = GET_ACCEPT_V(returnDecls, ObjectDecl);
-		rslt->dtors       = GET_ACCEPT_V(dtors      , Expr);
-
-		this->node = visitBaseExpr_SkipResultType( old, rslt );
-	}
-
-	virtual void visit( const UniqueExpr * old ) override final {
-		auto rslt = new ast::UniqueExpr(
-			old->location,
-			GET_ACCEPT_1(expr, Expr),
-			old->get_id()
-		);
-		rslt->object = GET_ACCEPT_1(object, ObjectDecl);
-		rslt->var    = GET_ACCEPT_1(var   , VariableExpr);
-
-		this->node = visitBaseExpr( old, rslt );
-	}
-
-	virtual void visit( const UntypedInitExpr * old ) override final {
-		std::deque<ast::InitAlternative> initAlts;
-		for (auto ia : old->initAlts) {
-			initAlts.push_back(ast::InitAlternative(
-				getAccept1< ast::Type, Type * >( ia.type ),
-				getAccept1< ast::Designation, Designation * >( ia.designation )
-			));
-		}
-		this->node = visitBaseExpr( old,
-			new ast::UntypedInitExpr(
-				old->location,
-				GET_ACCEPT_1(expr, Expr),
-				std::move(initAlts)
-			)
-		);
-	}
-
-	virtual void visit( const InitExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::InitExpr(
-				old->location,
-				GET_ACCEPT_1(expr, Expr),
-				GET_ACCEPT_1(designation, Designation)
-			)
-		);
-	}
-
-	virtual void visit( const DeletedExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::DeletedExpr(
-				old->location,
-				GET_ACCEPT_1(expr, Expr),
-				inCache(old->deleteStmt) ?
-					strict_dynamic_cast<ast::Decl*>(this->node) :
-					GET_ACCEPT_1(deleteStmt, Decl)
-			)
-		);
-	}
-
-	virtual void visit( const DefaultArgExpr * old ) override final {
-		this->node = visitBaseExpr( old,
-			new ast::DefaultArgExpr(
-				old->location,
-				GET_ACCEPT_1(expr, Expr)
-			)
-		);
-	}
-
-	virtual void visit( const GenericExpr * old ) override final {
-		std::vector<ast::GenericExpr::Association> associations;
-		for (auto association : old->associations) {
-			associations.push_back(ast::GenericExpr::Association(
-				getAccept1< ast::Type, Type * >( association.type ),
-				getAccept1< ast::Expr, Expression * >( association.expr )
-			));
-		}
-		this->node = visitBaseExpr( old,
-			new ast::GenericExpr(
-				old->location,
-				GET_ACCEPT_1(control, Expr),
-				std::move(associations)
-			)
-		);
-	}
-
-	void visitType( const Type * old, ast::Type * type ) {
-		// Some types do this in their constructor so add a check.
-		if ( !old->attributes.empty() && type->attributes.empty() ) {
-			type->attributes = GET_ACCEPT_V(attributes, Attribute);
-		}
-		this->node = type;
-	}
-
-	virtual void visit( const VoidType * old ) override final {
-		visitType( old, new ast::VoidType{ cv( old ) } );
-	}
-
-	virtual void visit( const BasicType * old ) override final {
-		auto type = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind, cv( old ) };
-		// I believe this should always be a BasicType.
-		if ( Validate::SizeType == old ) {
-			ast::sizeType = type;
-		}
-		visitType( old, type );
-	}
-
-	virtual void visit( const PointerType * old ) override final {
-		visitType( old, new ast::PointerType{
-			GET_ACCEPT_1( base, Type ),
-			GET_ACCEPT_1( dimension, Expr ),
-			(ast::LengthFlag)old->isVarLen,
-			(ast::DimensionFlag)old->isStatic,
-			cv( old )
-		} );
-	}
-
-	virtual void visit( const ArrayType * old ) override final {
-		visitType( old, new ast::ArrayType{
-			GET_ACCEPT_1( base, Type ),
-			GET_ACCEPT_1( dimension, Expr ),
-			(ast::LengthFlag)old->isVarLen,
-			(ast::DimensionFlag)old->isStatic,
-			cv( old )
-		} );
-	}
-
-	virtual void visit( const ReferenceType * old ) override final {
-		visitType( old, new ast::ReferenceType{
-			GET_ACCEPT_1( base, Type ),
-			cv( old )
-		} );
-	}
-
-	virtual void visit( const QualifiedType * old ) override final {
-		visitType( old, new ast::QualifiedType{
-			GET_ACCEPT_1( parent, Type ),
-			GET_ACCEPT_1( child, Type ),
-			cv( old )
-		} );
-	}
-
-	virtual void visit( const FunctionType * old ) override final {
-		auto ty = new ast::FunctionType {
-			(ast::ArgumentFlag)old->isVarArgs,
-			cv( old )
-		};
-		auto returnVars = GET_ACCEPT_V(returnVals, DeclWithType);
-		auto paramVars = GET_ACCEPT_V(parameters, DeclWithType);
-		// ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
-		// ty->params = GET_ACCEPT_V( parameters, DeclWithType );
-		for (auto & v: returnVars) {
-			ty->returns.emplace_back(v->get_type());
-		}
-		for (auto & v: paramVars) {
-			ty->params.emplace_back(v->get_type());
-		}
-		// xxx - when will this be non-null?
-		// will have to create dangling (no-owner) decls to be pointed to
-		auto foralls = GET_ACCEPT_V( forall, TypeDecl );
-
-		for (auto & param : foralls) {
-			ty->forall.emplace_back(new ast::TypeInstType(param));
-			for (auto asst : param->assertions) {
-				ty->assertions.emplace_back(
-					new ast::VariableExpr(param->location, asst));
-			}
-		}
-		visitType( old, ty );
-	}
-
-	void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) {
-		ty->params = GET_ACCEPT_V( parameters, Expr );
-		ty->hoistType = old->hoistType;
-		visitType( old, ty );
-	}
-
-	virtual void visit( const StructInstType * old ) override final {
-		ast::StructInstType * ty;
-		if ( old->baseStruct ) {
-			ty = new ast::StructInstType{
-				GET_ACCEPT_1( baseStruct, StructDecl ),
-				cv( old ),
-				GET_ACCEPT_V( attributes, Attribute )
-			};
-		} else {
-			ty = new ast::StructInstType{
-				old->name,
-				cv( old ),
-				GET_ACCEPT_V( attributes, Attribute )
-			};
-		}
-		postvisit( old, ty );
-	}
-
-	virtual void visit( const UnionInstType * old ) override final {
-		ast::UnionInstType * ty;
-		if ( old->baseUnion ) {
-			ty = new ast::UnionInstType{
-				GET_ACCEPT_1( baseUnion, UnionDecl ),
-				cv( old ),
-				GET_ACCEPT_V( attributes, Attribute )
-			};
-		} else {
-			ty = new ast::UnionInstType{
-				old->name,
-				cv( old ),
-				GET_ACCEPT_V( attributes, Attribute )
-			};
-		}
-		postvisit( old, ty );
-	}
-
-	virtual void visit( const EnumInstType * old ) override final {
-		ast::EnumInstType * ty;
-		if ( old->baseEnum ) {
-			ty = new ast::EnumInstType{
-				GET_ACCEPT_1( baseEnum, EnumDecl ),
-				cv( old ),
-				GET_ACCEPT_V( attributes, Attribute )
-			};
-		} else {
-			ty = new ast::EnumInstType{
-				old->name,
-				cv( old ),
-				GET_ACCEPT_V( attributes, Attribute )
-			};
-		}
-		postvisit( old, ty );
-	}
-
-	virtual void visit( const TraitInstType * old ) override final {
-		ast::TraitInstType * ty;
-		if ( old->baseTrait ) {
-			ty = new ast::TraitInstType{
-				GET_ACCEPT_1( baseTrait, TraitDecl ),
-				cv( old ),
-				GET_ACCEPT_V( attributes, Attribute )
-			};
-		} else {
-			ty = new ast::TraitInstType{
-				old->name,
-				cv( old ),
-				GET_ACCEPT_V( attributes, Attribute )
-			};
-		}
-		postvisit( old, ty );
-	}
-
-	virtual void visit( const TypeInstType * old ) override final {
-		ast::TypeInstType * ty;
-		if ( old->baseType ) {
-			ty = new ast::TypeInstType{
-				old->name,
-				GET_ACCEPT_1( baseType, TypeDecl ),
-				cv( old ),
-				GET_ACCEPT_V( attributes, Attribute )
-			};
-		} else {
-			ty = new ast::TypeInstType{
-				old->name,
-				old->isFtype ? ast::TypeDecl::Ftype : ast::TypeDecl::Dtype,
-				cv( old ),
-				GET_ACCEPT_V( attributes, Attribute )
-			};
-		}
-		postvisit( old, ty );
-	}
-
-	virtual void visit( const TupleType * old ) override final {
-		visitType( old, new ast::TupleType{
-			GET_ACCEPT_V( types, Type ),
-			// members generated by TupleType c'tor
-			cv( old )
-		} );
-	}
-
-	virtual void visit( const TypeofType * old ) override final {
-		visitType( old, new ast::TypeofType{
-			GET_ACCEPT_1( expr, Expr ),
-			(ast::TypeofType::Kind)old->is_basetypeof,
-			cv( old )
-		} );
-	}
-
-	virtual void visit( const VTableType * old ) override final {
-		visitType( old, new ast::VTableType{
-			GET_ACCEPT_1( base, Type ),
-			cv( old )
-		} );
-	}
-
-	virtual void visit( const AttrType * ) override final {
-		assertf( false, "AttrType deprecated in new AST." );
-	}
-
-	virtual void visit( const VarArgsType * old ) override final {
-		visitType( old, new ast::VarArgsType{ cv( old ) } );
-	}
-
-	virtual void visit( const ZeroType * old ) override final {
-		visitType( old, new ast::ZeroType{ cv( old ) } );
-	}
-
-	virtual void visit( const OneType * old ) override final {
-		visitType( old, new ast::OneType{ cv( old ) } );
-	}
-
-	virtual void visit( const GlobalScopeType * old ) override final {
-		visitType( old, new ast::GlobalScopeType{} );
-	}
-
-	virtual void visit( const Designation * old ) override final {
-		this->node = new ast::Designation(
-			old->location,
-			GET_ACCEPT_D(designators, Expr)
-		);
-	}
-
-	virtual void visit( const SingleInit * old ) override final {
-		this->node = new ast::SingleInit(
-			old->location,
-			GET_ACCEPT_1(value, Expr),
-			(old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::NoConstruct
-		);
-	}
-
-	virtual void visit( const ListInit * old ) override final {
-		this->node = new ast::ListInit(
-			old->location,
-			GET_ACCEPT_V(initializers, Init),
-			GET_ACCEPT_V(designations, Designation),
-			(old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::NoConstruct
-		);
-	}
-
-	virtual void visit( const ConstructorInit * old ) override final {
-		this->node = new ast::ConstructorInit(
-			old->location,
-			GET_ACCEPT_1(ctor, Stmt),
-			GET_ACCEPT_1(dtor, Stmt),
-			GET_ACCEPT_1(init, Init)
-		);
-	}
-
-	virtual void visit( const Constant * ) override final {
-		// Handled in visit( ConstantEpxr * ).
-		// In the new tree, Constant fields are inlined into containing ConstantExpression.
-		assert( 0 );
-	}
-
-	virtual void visit( const Attribute * old ) override final {
-		this->node = new ast::Attribute(
-			old->name,
-			GET_ACCEPT_V( parameters, Expr )
-		);
-	}
-};
-
-#undef GET_LABELS_V
-#undef GET_ACCEPT_V
-#undef GET_ACCEPT_1
-
-ast::TranslationUnit convert( const std::list< Declaration * > && translationUnit ) {
-	ConverterOldToNew c;
-	ast::TranslationUnit unit;
-	if (Validate::SizeType) {
-		// this should be a BasicType.
-		auto old = strict_dynamic_cast<BasicType *>(Validate::SizeType);
-		ast::sizeType = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind };
-	}
-
-	for(auto d : translationUnit) {
-		d->accept( c );
-		unit.decls.emplace_back( c.decl() );
-	}
-	deleteAll(translationUnit);
-
-	// Load the local static varables into the global store.
-	unit.global.sizeType = ast::sizeType;
-	unit.global.dereference = ast::dereferenceOperator;
-	unit.global.dtorStruct = ast::dtorStruct;
-	unit.global.dtorDestroy = ast::dtorStructDestroy;
-
-	return unit;
-}
Index: c/AST/Convert.hpp
===================================================================
--- src/AST/Convert.hpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,26 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// Convert.hpp -- Convert between the new and old syntax trees.
-//
-// Author           : Thierry Delisle
-// Created On       : Thu May 09 15::37::05 2019
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri May 17 11:25:00 2019
-// Update Count     : 1
-//
-
-#pragma once
-
-#include <list>
-
-class Declaration;
-namespace ast {
-	class TranslationUnit;
-};
-
-std::list< Declaration * > convert( const ast::TranslationUnit && translationUnit );
-ast::TranslationUnit convert( const std::list< Declaration * > && translationUnit );
Index: src/AST/Decl.cpp
===================================================================
--- src/AST/Decl.cpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/AST/Decl.cpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -20,5 +20,4 @@
 #include <unordered_map>
 
-#include "CodeGen/FixMain.h"   // for FixMain
 #include "Common/Eval.h"       // for eval
 
@@ -76,10 +75,4 @@
 	}
 	this->type = ftype;
-	// Hack forcing the function "main" to have Cforall linkage to replace
-	// main even if it is inside an extern "C", and also makes sure the
-	// replacing function is always a C function.
-	if ( name == "main" ) {
-		this->linkage = CodeGen::FixMain::getMainLinkage();
-	}
 }
 
@@ -108,8 +101,4 @@
 	}
 	this->type = type;
-	// See note above about this hack.
-	if ( name == "main" ) {
-		this->linkage = CodeGen::FixMain::getMainLinkage();
-	}
 }
 
Index: src/AST/SymbolTable.cpp
===================================================================
--- src/AST/SymbolTable.cpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/AST/SymbolTable.cpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -39,5 +39,5 @@
 	static inline auto stats() {
 		using namespace Stats::Counters;
-		static auto group   = build<CounterGroup>("Indexers");
+		static auto group   = build<CounterGroup>("Symbol Tables");
 		static struct {
 			SimpleCounter * count;
Index: src/AST/SymbolTable.hpp
===================================================================
--- src/AST/SymbolTable.hpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/AST/SymbolTable.hpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -88,5 +88,5 @@
 	using Ptr = std::shared_ptr<const SymbolTable>;
 
-	Ptr prevScope;                 ///< Indexer for parent scope
+	Ptr prevScope;                 ///< Symbol Table for parent scope
 	unsigned long scope;           ///< Scope index of this indexer
 	unsigned long repScope;        ///< Scope index of currently represented scope
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/AST/Type.hpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -34,6 +34,4 @@
 
 namespace ast {
-
-template< typename T > class Pass;
 
 class Type : public Node {
Index: src/AST/module.mk
===================================================================
--- src/AST/module.mk	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/AST/module.mk	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -20,6 +20,4 @@
 	AST/Bitfield.hpp \
 	AST/Chain.hpp \
-	AST/Convert.cpp \
-	AST/Convert.hpp \
 	AST/Copy.cpp \
 	AST/Copy.hpp \
Index: src/BasicTypes-gen.cc
===================================================================
--- src/BasicTypes-gen.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/BasicTypes-gen.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -272,50 +272,4 @@
 	size_t start, end;
 
-
-	#define TypeH TOP_SRCDIR "src/SynTree/Type.h"
-	resetInput( file, TypeH, buffer, code, str );
-
-	if ( (start = str.find( STARTMK )) == string::npos ) Abort( "start", TypeH );
-	start += sizeof( STARTMK );							// includes newline
-	code << str.substr( 0, start );
-
-	code << "\t" << BYMK << endl;
-	code << "\tenum Kind {" << endl;
-	for ( int r = 0; r < NUMBER_OF_BASIC_TYPES; r += 1 ) {
-		code << "\t\t" << graph[r].name << "," << endl;
-	} // for
-	code << "\t\tNUMBER_OF_BASIC_TYPES" << endl;
-	code << "\t} kind;" << endl;
-	code << "\t";										// indentation for end marker
-
-	if ( (start = str.find( ENDMK, start + 1 )) == string::npos ) Abort( "end", TypeH );
-	code << str.substr( start );
-
-	output( file, TypeH, code );
-	// cout << code.str();
-
-
-	#define TypeC TOP_SRCDIR "src/SynTree/Type.cc"
-	resetInput( file, TypeC, buffer, code, str );
-
-	if ( (start = str.find( STARTMK )) == string::npos ) Abort( "start", TypeC );
-	start += sizeof( STARTMK );							// includes newline
-	code << str.substr( 0, start );
-
-	code << BYMK << endl;
-	code << "const char * BasicType::typeNames[] = {" << endl;
-	for ( int r = 0; r < NUMBER_OF_BASIC_TYPES; r += 1 ) {
-		code << "\t\"" << graph[r].type << "\"," << endl;
-	} // for
-	code << "};" << endl;
-
-	if ( (start = str.find( ENDMK, start + 1 )) == string::npos ) Abort( "end", TypeC );
-	code << str.substr( start );
-
-	output( file, TypeC, code );
-	// cout << code.str();
-
-
-	// TEMPORARY DURING CHANGE OVER
 	#define TypeH_AST TOP_SRCDIR "src/AST/Type.hpp"
 	resetInput( file, TypeH_AST, buffer, code, str );
Index: c/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,1255 +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.
-//
-// CodeGenerator.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed Jun 29 14:34:00 2022
-// Update Count     : 542
-//
-#include "CodeGenerator.h"
-
-#include <cassert>                   // for assert, assertf
-#include <list>                      // for _List_iterator, list, list<>::it...
-#include <sstream>                   // for stringstream
-
-#include "AST/Decl.hpp"              // for DeclWithType
-#include "Common/UniqueName.h"       // for UniqueName
-#include "GenType.h"                 // for genType
-#include "InitTweak/InitTweak.h"     // for getPointerBase
-#include "OperatorTable.h"           // for OperatorInfo, operatorLookup
-#include "SynTree/LinkageSpec.h"     // for Spec, Intrinsic
-#include "SynTree/Attribute.h"       // for Attribute
-#include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
-#include "SynTree/Constant.h"        // for Constant
-#include "SynTree/Declaration.h"     // for DeclarationWithType, TypeDecl
-#include "SynTree/Expression.h"      // for Expression, UntypedExpr, Applica...
-#include "SynTree/Initializer.h"     // for Initializer, ListInit, Designation
-#include "SynTree/Label.h"           // for Label, operator<<
-#include "SynTree/Statement.h"       // for Statement, AsmStmt, BranchStmt
-#include "SynTree/Type.h"            // for Type, Type::StorageClasses, Func...
-
-using namespace std;
-
-namespace CodeGen {
-	int CodeGenerator::tabsize = 4;
-
-	// The kinds of statements that would ideally be followed by whitespace.
-	bool wantSpacing( Statement * stmt) {
-		return dynamic_cast< IfStmt * >( stmt ) || dynamic_cast< CompoundStmt * >( stmt ) ||
-			dynamic_cast< WhileDoStmt * >( stmt ) || dynamic_cast< ForStmt * >( stmt ) || dynamic_cast< SwitchStmt *>( stmt );
-	}
-
-	void CodeGenerator::extension( Expression * expr ) {
-		if ( expr->get_extension() ) {
-			output << "__extension__ ";
-		} // if
-	} // extension
-
-	void CodeGenerator::extension( Declaration * decl ) {
-		if ( decl->get_extension() ) {
-			output << "__extension__ ";
-		} // if
-	} // extension
-
-	void CodeGenerator::asmName( DeclarationWithType * decl ) {
-		if ( ConstantExpr * asmName = dynamic_cast<ConstantExpr *>(decl->get_asmName()) ) {
-			output << " asm ( " << asmName->get_constant()->get_value() << " )";
-		} // if
-	} // extension
-
-	CodeGenerator::LabelPrinter & CodeGenerator::LabelPrinter::operator()( std::list< Label > & l ) {
-		labels = &l;
-		return *this;
-	}
-
-	ostream & operator<<( ostream & output, CodeGenerator::LabelPrinter & printLabels ) {
-		std::list< Label > & labs = *printLabels.labels;
-		// l.unique(); // assumes a sorted list. Why not use set? Does order matter?
-		for ( Label & l : labs ) {
-			output << l.get_name() + ": ";
-			printLabels.cg.genAttributes( l.get_attributes() );
-		} // for
-		return output;
-	}
-
-	// Using updateLocation at the beginning of a node and endl within a node should become the method of formating.
-	void CodeGenerator::updateLocation( CodeLocation const & to ) {
-		// skip if linemarks shouldn't appear or if codelocation is unset
-		if ( !options.lineMarks || to.isUnset() ) return;
-
-		if ( currentLocation.followedBy( to, 0 ) ) {
-			return;
-		} else if ( currentLocation.followedBy( to, 1 ) ) {
-			output << "\n" << indent;
-			currentLocation.first_line += 1;
-		} else if ( currentLocation.followedBy( to, 2 ) ) {
-			output << "\n\n" << indent;
-			currentLocation.first_line += 2;
-		} else {
-			output << "\n# " << to.first_line << " \"" << to.filename
-				   << "\"\n" << indent;
-			currentLocation = to;
-		}
-		output << std::flush;
-	}
-
-	void CodeGenerator::updateLocation( BaseSyntaxNode const * to ) {
-		updateLocation( to->location );
-	}
-
-	// replace endl
-	ostream & CodeGenerator::LineEnder::operator()( ostream & os ) const {
-		// if ( !cg.lineMarks ) {
-		// 	os << "\n" << cg.indent << std::flush;
-		// }
-		os << "\n" << std::flush;
-		cg.currentLocation.first_line++;
-		// os << "/* did endl; current loc is: " << cg.currentLocation.first_line << "*/";
-		return os;
-	}
-
-	CodeGenerator::CodeGenerator( std::ostream & os, bool pretty, bool genC, bool lineMarks, bool printExprTypes ) : indent( 0, CodeGenerator::tabsize ), output( os ), printLabels( *this ), options( pretty, genC, lineMarks, printExprTypes ), endl( *this ) {}
-	CodeGenerator::CodeGenerator( std::ostream & os, const Options &options ) : indent( 0, CodeGenerator::tabsize ), output( os ), printLabels( *this ), options(options), endl( *this ) {}
-
-	string CodeGenerator::mangleName( DeclarationWithType * decl ) {
-		// GCC builtins should always be printed unmangled
-		if ( options.pretty || decl->linkage.is_gcc_builtin ) return decl->name;
-		if ( LinkageSpec::isMangled(decl->linkage) && decl->mangleName != "" ) {
-			// need to incorporate scope level in order to differentiate names for destructors
-			return decl->get_scopedMangleName();
-		} else {
-			return decl->name;
-		} // if
-	}
-
-	void CodeGenerator::genAttributes( list< Attribute * > & attributes ) {
-		if ( attributes.empty() ) return;
-		output << "__attribute__ ((";
-		for ( list< Attribute * >::iterator attr( attributes.begin() );; ) {
-			output << (*attr)->name;
-			if ( ! (*attr)->parameters.empty() ) {
-				output << "(";
-				genCommaList( (*attr)->parameters.begin(), (*attr)->parameters.end() );
-				output << ")";
-			} // if
-			if ( ++attr == attributes.end() ) break;
-			output << ",";								// separator
-		} // for
-		output << ")) ";
-	} // CodeGenerator::genAttributes
-
-	// *** BaseSyntaxNode
-	void CodeGenerator::previsit( BaseSyntaxNode * node ) {
-		// turn off automatic recursion for all nodes, to allow each visitor to
-		// precisely control the order in which its children are visited.
-		visit_children = false;
-		updateLocation( node );
-	}
-
-	// *** BaseSyntaxNode
-	void CodeGenerator::postvisit( BaseSyntaxNode * node ) {
-		std::stringstream ss;
-		node->print( ss );
-		assertf( false, "Unhandled node reached in CodeGenerator: %s", ss.str().c_str() );
-	}
-
-	// *** Expression
-	void CodeGenerator::previsit( Expression * node ) {
-		previsit( (BaseSyntaxNode *)node );
-		GuardAction( [this, node](){
-				if ( options.printExprTypes && node->result ) {
-					output << " /* " << genType( node->result, "", options ) << " */ ";
-				}
-			} );
-	}
-
-	// *** Declarations
-	void CodeGenerator::postvisit( FunctionDecl * functionDecl ) {
-		// deleted decls should never be used, so don't print them
-		if ( functionDecl->isDeleted && options.genC ) return;
-		extension( functionDecl );
-		genAttributes( functionDecl->get_attributes() );
-
-		handleStorageClass( functionDecl );
-		functionDecl->get_funcSpec().print( output );
-
-		Options subOptions = options;
-		subOptions.anonymousUnused = functionDecl->has_body();
-		output << genType( functionDecl->get_functionType(), mangleName( functionDecl ), subOptions );
-
-		asmName( functionDecl );
-
-		if ( functionDecl->get_statements() ) {
-			functionDecl->get_statements()->accept( *visitor );
-		} // if
-		if ( functionDecl->isDeleted ) {
-			output << " = void";
-		}
-	}
-
-	void CodeGenerator::postvisit( ObjectDecl * objectDecl ) {
-		// deleted decls should never be used, so don't print them
-		if ( objectDecl->isDeleted && options.genC ) return;
-
-		// gcc allows an empty declarator (no name) for bit-fields and C states: 6.7.2.1 Structure and union specifiers,
-		// point 4, page 113: If the (bit field) value is zero, the declaration shall have no declarator.  For anything
-		// else, the anonymous name refers to the anonymous object for plan9 inheritance.
-		if ( objectDecl->get_name().empty() && options.genC && ! objectDecl->get_bitfieldWidth() ) {
-			// only generate an anonymous name when generating C code, otherwise it clutters the output too much
-			static UniqueName name = { "__anonymous_object" };
-			objectDecl->set_name( name.newName() );
-			// Stops unused parameter warnings.
-			if ( options.anonymousUnused ) {
-				objectDecl->attributes.push_back( new Attribute( "unused" ) );
-			}
-		}
-
-		extension( objectDecl );
-		genAttributes( objectDecl->get_attributes() );
-
-		handleStorageClass( objectDecl );
-		output << genType( objectDecl->get_type(), mangleName( objectDecl ), options.pretty, options.genC );
-
-		asmName( objectDecl );
-
-		if ( objectDecl->get_init() ) {
-			output << " = ";
-			objectDecl->get_init()->accept( *visitor );
-		} // if
-		if ( objectDecl->isDeleted ) {
-			output << " = void";
-		}
-
-		if ( objectDecl->get_bitfieldWidth() ) {
-			output << ":";
-			objectDecl->get_bitfieldWidth()->accept( *visitor );
-		} // if
-	}
-
-	void CodeGenerator::handleAggregate( AggregateDecl * aggDecl, const std::string & kind ) {
-		if( ! aggDecl->parameters.empty() && ! options.genC ) {
-			// assertf( ! genC, "Aggregate type parameters should not reach code generation." );
-			output << "forall(";
-			genCommaList( aggDecl->parameters.begin(), aggDecl->parameters.end() );
-			output << ")" << endl;
-			output << indent;
-		}
-
-		output << kind;
-		genAttributes( aggDecl->attributes );
-		output << aggDecl->name;
-
-		if ( aggDecl->has_body() ) {
-			std::list< Declaration * > & memb = aggDecl->members;
-			output << " {" << endl;
-
-			++indent;
-			for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end(); i++ ) {
-				output << indent;
-				(*i)->accept( *visitor );
-				output << ";" << endl;
-			} // for
-
-			--indent;
-
-			output << indent << "}";
-		} // if
-	}
-
-	void CodeGenerator::postvisit( StructDecl * structDecl ) {
-		extension( structDecl );
-		handleAggregate( structDecl, "struct " );
-	}
-
-	void CodeGenerator::postvisit( UnionDecl * unionDecl ) {
-		extension( unionDecl );
-		handleAggregate( unionDecl, "union " );
-	}
-
-	template<typename pass_type>
-	inline void genEnumInitializer( PassVisitor<pass_type> * visitor, Type * baseType, std::ostream & output,
-	Initializer * init, long long * cur_val, Options options) {
-		auto baseTypeAsBasic = baseType ? dynamic_cast<BasicType *>( baseType ) : nullptr;
-		if ( init ) { // If value has an explicit initiazatior 
-			output << " = "; 
-			output << "(" << genType(baseType, "", options) << ")";
-			init->accept( *visitor );
-			if ( baseTypeAsBasic && baseTypeAsBasic->isInteger() ) { // if it is an integral type and initilizer offered, 
-			// need to update the cur_val
-				Expression* expr = ((SingleInit *)(init))->value;
-				while ( auto temp = dynamic_cast<CastExpr *>(expr) ) { // unwrap introduced cast
-					expr = temp->arg;
-				}
-				*cur_val = ((ConstantExpr *)expr)->constant.get_ival()+1;
-			}
-		} else if ( baseTypeAsBasic && baseTypeAsBasic->isInteger() ) { // integral implicitly init to cur_val + 1
-			output << " = " << "(" << genType(baseType, "", options) << ")";
-			output << (*cur_val)++;
-		}
-	}
-
-	void CodeGenerator::postvisit( EnumDecl * enumDecl ) {
-		extension( enumDecl );
-		std::list< Declaration* > &memb = enumDecl->get_members();
-		if (enumDecl->base && ! memb.empty()) {
-			long long cur_val = 0;
-			for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
-				ObjectDecl * obj = dynamic_cast< ObjectDecl* >( *i );
-				assert( obj );
-				output << "static ";
-				output << genType(enumDecl->base, mangleName( obj ), options);
-				genEnumInitializer( visitor, enumDecl->base, output, obj->get_init(), &cur_val, options);
-				output << ";" << endl;
-			} // for
-		} else {
-			output << "enum ";
-			genAttributes( enumDecl->get_attributes() );
-
-			output << enumDecl->get_name();
-
-			if ( ! memb.empty() ) {
-				output << " {" << endl;
-
-				++indent;
-				for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
-					ObjectDecl * obj = dynamic_cast< ObjectDecl* >( *i );
-					assert( obj );
-					output << indent << mangleName( obj );
-					if ( obj->get_init() ) {
-						output << " = ";
-						obj->get_init()->accept( *visitor );
-					} // if
-					output << "," << endl;
-				} // for
-			--indent;
-			output << indent << "}";
-			} // if
-		} // if
-	}
-
-	void CodeGenerator::postvisit( TraitDecl * traitDecl ) {
-		assertf( ! options.genC, "TraitDecls should not reach code generation." );
-		extension( traitDecl );
-		handleAggregate( traitDecl, "trait " );
-	}
-
-	void CodeGenerator::postvisit( TypedefDecl * typeDecl ) {
-		assertf( ! options.genC, "Typedefs are removed and substituted in earlier passes." );
-		output << "typedef ";
-		output << genType( typeDecl->get_base(), typeDecl->get_name(), options ) << endl;
-	}
-
-	void CodeGenerator::postvisit( TypeDecl * typeDecl ) {
-		assertf( ! options.genC, "TypeDecls should not reach code generation." );
-		output << typeDecl->genTypeString() << " " << typeDecl->name;
-		if ( typeDecl->sized ) {
-			output << " | sized(" << typeDecl->name << ")";
-		}
-		if ( ! typeDecl->assertions.empty() ) {
-			output << " | { ";
-			for ( DeclarationWithType * assert :  typeDecl->assertions ) {
-				assert->accept( *visitor );
-				output << "; ";
-			}
-			output << " }";
-		}
-	}
-
-	void CodeGenerator::postvisit( StaticAssertDecl * assertDecl ) {
-		output << "_Static_assert(";
-		assertDecl->condition->accept( *visitor );
-		output << ", ";
-		assertDecl->message->accept( *visitor );
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( Designation * designation ) {
-		std::list< Expression * > designators = designation->get_designators();
-		if ( designators.size() == 0 ) return;
-		for ( Expression * des : designators ) {
-			if ( dynamic_cast< NameExpr * >( des ) || dynamic_cast< VariableExpr * >( des ) ) {
-				// if expression is a NameExpr or VariableExpr, then initializing aggregate member
-				output << ".";
-				des->accept( *visitor );
-			} else {
-				// otherwise, it has to be a ConstantExpr or CastExpr, initializing array element
-				output << "[";
-				des->accept( *visitor );
-				output << "]";
-			} // if
-		} // for
-		output << " = ";
-	}
-
-	void CodeGenerator::postvisit( SingleInit * init ) {
-		init->get_value()->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( ListInit * init ) {
-		auto initBegin = init->begin();
-		auto initEnd = init->end();
-		auto desigBegin = init->get_designations().begin();
-		auto desigEnd = init->get_designations().end();
-
-		output << "{ ";
-		for ( ; initBegin != initEnd && desigBegin != desigEnd; ) {
-			(*desigBegin)->accept( *visitor );
-			(*initBegin)->accept( *visitor );
-			++initBegin, ++desigBegin;
-			if ( initBegin != initEnd ) {
-				output << ", ";
-			}
-		}
-		output << " }";
-		assertf( initBegin == initEnd && desigBegin == desigEnd, "Initializers and designators not the same length. %s", toString( init ).c_str() );
-	}
-
-	void CodeGenerator::postvisit( ConstructorInit * init ){
-		assertf( ! options.genC, "ConstructorInit nodes should not reach code generation." );
-		// pseudo-output for constructor/destructor pairs
-		output << "<ctorinit>{" << endl << ++indent << "ctor: ";
-		maybeAccept( init->get_ctor(), *visitor );
-		output << ", " << endl << indent << "dtor: ";
-		maybeAccept( init->get_dtor(), *visitor );
-		output << endl << --indent << "}";
-	}
-
-	void CodeGenerator::postvisit( Constant * constant ) {
-		output << constant->get_value();
-	}
-
-	// *** Expressions
-	void CodeGenerator::postvisit( ApplicationExpr * applicationExpr ) {
-		extension( applicationExpr );
-		if ( VariableExpr * varExpr = dynamic_cast< VariableExpr* >( applicationExpr->get_function() ) ) {
-			const OperatorInfo * opInfo;
-			if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && ( opInfo = operatorLookup( varExpr->get_var()->get_name() ) ) ) {
-				std::list< Expression* >::iterator arg = applicationExpr->get_args().begin();
-				switch ( opInfo->type ) {
-				  case OT_INDEX:
-					assert( applicationExpr->get_args().size() == 2 );
-					(*arg++)->accept( *visitor );
-					output << "[";
-					(*arg)->accept( *visitor );
-					output << "]";
-					break;
-
-				  case OT_CALL:
-					// there are no intrinsic definitions of the function call operator
-					assert( false );
-					break;
-
-				  case OT_CTOR:
-				  case OT_DTOR:
-					if ( applicationExpr->get_args().size() == 1 ) {
-						// the expression fed into a single parameter constructor or destructor may contain side
-						// effects, so must still output this expression
-						output << "(";
-						(*arg++)->accept( *visitor );
-						output << ") /* " << opInfo->inputName << " */";
-					} else if ( applicationExpr->get_args().size() == 2 ) {
-						// intrinsic two parameter constructors are essentially bitwise assignment
-						output << "(";
-						(*arg++)->accept( *visitor );
-						output << opInfo->symbol;
-						(*arg)->accept( *visitor );
-						output << ") /* " << opInfo->inputName << " */";
-					} else {
-						// no constructors with 0 or more than 2 parameters
-						assert( false );
-					} // if
-					break;
-
-				  case OT_PREFIX:
-				  case OT_PREFIXASSIGN:
-					assert( applicationExpr->get_args().size() == 1 );
-					output << "(";
-					output << opInfo->symbol;
-					(*arg)->accept( *visitor );
-					output << ")";
-					break;
-
-				  case OT_POSTFIX:
-				  case OT_POSTFIXASSIGN:
-					assert( applicationExpr->get_args().size() == 1 );
-					(*arg)->accept( *visitor );
-					output << opInfo->symbol;
-					break;
-
-
-				  case OT_INFIX:
-				  case OT_INFIXASSIGN:
-					assert( applicationExpr->get_args().size() == 2 );
-					output << "(";
-					(*arg++)->accept( *visitor );
-					output << opInfo->symbol;
-					(*arg)->accept( *visitor );
-					output << ")";
-					break;
-
-				  case OT_CONSTANT:
-				  case OT_LABELADDRESS:
-					// there are no intrinsic definitions of 0/1 or label addresses as functions
-					assert( false );
-				} // switch
-			} else if( varExpr->get_var()->get_linkage() == LinkageSpec::BuiltinCFA && varExpr->get_var()->get_name() == "intptr" ) {
-				// THIS is a hack to make it a constant until a proper constexpr solution is created
-				output << "((void*)";
-				std::list< Expression* >::iterator arg = applicationExpr->get_args().begin();
-				(*arg++)->accept( *visitor );
-				output << ")";
-			} else {
-				varExpr->accept( *visitor );
-				output << "(";
-				genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
-				output << ")";
-			} // if
-		} else {
-			applicationExpr->get_function()->accept( *visitor );
-			output << "(";
-			genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
-			output << ")";
-		} // if
-	}
-
-	void CodeGenerator::postvisit( UntypedExpr * untypedExpr ) {
-		extension( untypedExpr );
-		if ( NameExpr * nameExpr = dynamic_cast< NameExpr* >( untypedExpr->function ) ) {
-			const OperatorInfo * opInfo = operatorLookup( nameExpr->name );
-			if ( opInfo ) {
-				std::list< Expression* >::iterator arg = untypedExpr->args.begin();
-				switch ( opInfo->type ) {
-				  case OT_INDEX:
-					assert( untypedExpr->args.size() == 2 );
-					(*arg++)->accept( *visitor );
-					output << "[";
-					(*arg)->accept( *visitor );
-					output << "]";
-					break;
-
-				  case OT_CALL:
-					assert( false );
-
-				  case OT_CTOR:
-				  case OT_DTOR:
-					if ( untypedExpr->args.size() == 1 ) {
-						// the expression fed into a single parameter constructor or destructor may contain side
-						// effects, so must still output this expression
-						output << "(";
-						(*arg++)->accept( *visitor );
-						output << ") /* " << opInfo->inputName << " */";
-					} else if ( untypedExpr->get_args().size() == 2 ) {
-						// intrinsic two parameter constructors are essentially bitwise assignment
-						output << "(";
-						(*arg++)->accept( *visitor );
-						output << opInfo->symbol;
-						(*arg)->accept( *visitor );
-						output << ") /* " << opInfo->inputName << " */";
-					} else {
-						// no constructors with 0 or more than 2 parameters
-						assertf( ! options.genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." );
-						output << "(";
-						(*arg++)->accept( *visitor );
-						output << opInfo->symbol << "{ ";
-						genCommaList( arg, untypedExpr->args.end() );
-						output << "}) /* " << opInfo->inputName << " */";
-					} // if
-					break;
-
-				  case OT_PREFIX:
-				  case OT_PREFIXASSIGN:
-				  case OT_LABELADDRESS:
-					assert( untypedExpr->args.size() == 1 );
-					output << "(";
-					output << opInfo->symbol;
-					(*arg)->accept( *visitor );
-					output << ")";
-					break;
-
-				  case OT_POSTFIX:
-				  case OT_POSTFIXASSIGN:
-					assert( untypedExpr->args.size() == 1 );
-					(*arg)->accept( *visitor );
-					output << opInfo->symbol;
-					break;
-
-				  case OT_INFIX:
-				  case OT_INFIXASSIGN:
-					assert( untypedExpr->args.size() == 2 );
-					output << "(";
-					(*arg++)->accept( *visitor );
-					output << opInfo->symbol;
-					(*arg)->accept( *visitor );
-					output << ")";
-					break;
-
-				  case OT_CONSTANT:
-					// there are no intrinsic definitions of 0 or 1 as functions
-					assert( false );
-				} // switch
-			} else {
-				// builtin routines
-				nameExpr->accept( *visitor );
-				output << "(";
-				genCommaList( untypedExpr->args.begin(), untypedExpr->args.end() );
-				output << ")";
-			} // if
-		} else {
-			untypedExpr->function->accept( *visitor );
-			output << "(";
-			genCommaList( untypedExpr->args.begin(), untypedExpr->args.end() );
-			output << ")";
-		} // if
-	}
-
-	void CodeGenerator::postvisit( RangeExpr * rangeExpr ) {
-		rangeExpr->low->accept( *visitor );
-		output << " ... ";
-		rangeExpr->high->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( NameExpr * nameExpr ) {
-		extension( nameExpr );
-		const OperatorInfo * opInfo = operatorLookup( nameExpr->name );
-		if ( opInfo ) {
-			if ( opInfo->type == OT_CONSTANT ) {
-				output << opInfo->symbol;
-			} else {
-				output << opInfo->outputName;
-			}
-		} else {
-			output << nameExpr->get_name();
-		} // if
-	}
-
-	void CodeGenerator::postvisit( DimensionExpr * dimensionExpr ) {
-		extension( dimensionExpr );
-		output << "/*non-type*/" << dimensionExpr->get_name();
-	}
-
-	void CodeGenerator::postvisit( AddressExpr * addressExpr ) {
-		extension( addressExpr );
-		output << "(&";
-		addressExpr->arg->accept( *visitor );
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( LabelAddressExpr *addressExpr ) {
-		extension( addressExpr );
-		output << "(&&" << addressExpr->arg << ")";
-	}
-
-	void CodeGenerator::postvisit( CastExpr * castExpr ) {
-		extension( castExpr );
-		output << "(";
-		if ( castExpr->get_result()->isVoid() ) {
-			output << "(void)";
-		} else {
-			// at least one result type of cast.
-			// Note: previously, lvalue casts were skipped. Since it's now impossible for the user to write
-			// an lvalue cast, this has been taken out.
-			output << "(";
-			output << genType( castExpr->get_result(), "", options );
-			output << ")";
-		} // if
-		castExpr->arg->accept( *visitor );
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( KeywordCastExpr * castExpr ) {
-		assertf( ! options.genC, "KeywordCast should not reach code generation." );
-		extension( castExpr );
-		output << "((" << castExpr->targetString() << " &)";
-		castExpr->arg->accept( *visitor );
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( VirtualCastExpr * castExpr ) {
-		assertf( ! options.genC, "VirtualCastExpr should not reach code generation." );
-		extension( castExpr );
-		output << "(virtual ";
-		castExpr->get_arg()->accept( *visitor );
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( UntypedMemberExpr * memberExpr ) {
-		assertf( ! options.genC, "UntypedMemberExpr should not reach code generation." );
-		extension( memberExpr );
-		memberExpr->get_aggregate()->accept( *visitor );
-		output << ".";
-		memberExpr->get_member()->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( MemberExpr * memberExpr ) {
-		extension( memberExpr );
-		memberExpr->get_aggregate()->accept( *visitor );
-		output << "." << mangleName( memberExpr->get_member() );
-	}
-
-	void CodeGenerator::postvisit( VariableExpr * variableExpr ) {
-		extension( variableExpr );
-		const OperatorInfo * opInfo;
-		if( dynamic_cast<ZeroType*>( variableExpr->get_var()->get_type() ) ) {
-			output << "0";
-		} else if ( variableExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && (opInfo = operatorLookup( variableExpr->get_var()->get_name() )) && opInfo->type == OT_CONSTANT ) {
-			output << opInfo->symbol;
-		} else {
-			output << mangleName( variableExpr->get_var() );
-		} // if
-	}
-
-	void CodeGenerator::postvisit( ConstantExpr * constantExpr ) {
-		assert( constantExpr->get_constant() );
-		extension( constantExpr );
-		constantExpr->get_constant()->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( SizeofExpr * sizeofExpr ) {
-		extension( sizeofExpr );
-		output << "sizeof(";
-		if ( sizeofExpr->get_isType() ) {
-			output << genType( sizeofExpr->get_type(), "", options );
-		} else {
-			sizeofExpr->get_expr()->accept( *visitor );
-		} // if
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( AlignofExpr * alignofExpr ) {
-		// use GCC extension to avoid bumping std to C11
-		extension( alignofExpr );
-		output << "__alignof__(";
-		if ( alignofExpr->get_isType() ) {
-			output << genType( alignofExpr->get_type(), "", options );
-		} else {
-			alignofExpr->get_expr()->accept( *visitor );
-		} // if
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( UntypedOffsetofExpr * offsetofExpr ) {
-		assertf( ! options.genC, "UntypedOffsetofExpr should not reach code generation." );
-		output << "offsetof(";
-		output << genType( offsetofExpr->get_type(), "", options );
-		output << ", " << offsetofExpr->get_member();
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( OffsetofExpr * offsetofExpr ) {
-		// use GCC builtin
-		output << "__builtin_offsetof(";
-		output << genType( offsetofExpr->get_type(), "", options );
-		output << ", " << mangleName( offsetofExpr->get_member() );
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( OffsetPackExpr * offsetPackExpr ) {
-		assertf( ! options.genC, "OffsetPackExpr should not reach code generation." );
-		output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", options ) << ")";
-	}
-
-	void CodeGenerator::postvisit( LogicalExpr * logicalExpr ) {
-		extension( logicalExpr );
-		output << "(";
-		logicalExpr->get_arg1()->accept( *visitor );
-		if ( logicalExpr->get_isAnd() ) {
-			output << " && ";
-		} else {
-			output << " || ";
-		} // if
-		logicalExpr->get_arg2()->accept( *visitor );
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( ConditionalExpr * conditionalExpr ) {
-		extension( conditionalExpr );
-		output << "(";
-		conditionalExpr->get_arg1()->accept( *visitor );
-		output << " ? ";
-		conditionalExpr->get_arg2()->accept( *visitor );
-		output << " : ";
-		conditionalExpr->get_arg3()->accept( *visitor );
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( CommaExpr * commaExpr ) {
-		extension( commaExpr );
-		output << "(";
-		if ( options.genC ) {
-			// arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings.
-			commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) );
-		}
-		commaExpr->get_arg1()->accept( *visitor );
-		output << " , ";
-		commaExpr->get_arg2()->accept( *visitor );
-		output << ")";
-	}
-
-	void CodeGenerator::postvisit( TupleAssignExpr * tupleExpr ) {
-		assertf( ! options.genC, "TupleAssignExpr should not reach code generation." );
-		tupleExpr->stmtExpr->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( UntypedTupleExpr * tupleExpr ) {
-		assertf( ! options.genC, "UntypedTupleExpr should not reach code generation." );
-		extension( tupleExpr );
-		output << "[";
-		genCommaList( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end() );
-		output << "]";
-	}
-
-	void CodeGenerator::postvisit( TupleExpr * tupleExpr ) {
-		assertf( ! options.genC, "TupleExpr should not reach code generation." );
-		extension( tupleExpr );
-		output << "[";
-		genCommaList( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end() );
-		output << "]";
-	}
-
-	void CodeGenerator::postvisit( TupleIndexExpr * tupleExpr ) {
-		assertf( ! options.genC, "TupleIndexExpr should not reach code generation." );
-		extension( tupleExpr );
-		tupleExpr->get_tuple()->accept( *visitor );
-		output << "." << tupleExpr->get_index();
-	}
-
-	void CodeGenerator::postvisit( TypeExpr * typeExpr ) {
-		// if ( options.genC ) std::cerr << "typeexpr still exists: " << typeExpr << std::endl;
-		// assertf( ! options.genC, "TypeExpr should not reach code generation." );
-		if ( ! options.genC ) {
-			output << genType( typeExpr->get_type(), "", options );
-		}
-	}
-
-	void CodeGenerator::postvisit( AsmExpr * asmExpr ) {
-		if ( !asmExpr->inout.empty() ) {
-			output << "[ ";
-			output << asmExpr->inout;
-			output << " ] ";
-		} // if
-		asmExpr->constraint->accept( *visitor );
-		output << " ( ";
-		asmExpr->operand->accept( *visitor );
-		output << " )";
-	}
-
-	void CodeGenerator::postvisit( CompoundLiteralExpr *compLitExpr ) {
-		assert( compLitExpr->get_result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) );
-		output << "(" << genType( compLitExpr->get_result(), "", options ) << ")";
-		compLitExpr->get_initializer()->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( UniqueExpr * unqExpr ) {
-		assertf( ! options.genC, "Unique expressions should not reach code generation." );
-		output << "unq<" << unqExpr->get_id() << ">{ ";
-		unqExpr->get_expr()->accept( *visitor );
-		output << " }";
-	}
-
-	void CodeGenerator::postvisit( StmtExpr * stmtExpr ) {
-		std::list< Statement * > & stmts = stmtExpr->statements->kids;
-		output << "({" << endl;
-		++indent;
-		unsigned int numStmts = stmts.size();
-		unsigned int i = 0;
-		for ( Statement * stmt : stmts ) {
-			output << indent << printLabels( stmt->get_labels() );
-			if ( i+1 == numStmts ) {
-				// last statement in a statement expression needs to be handled specially -
-				// cannot cast to void, otherwise the expression statement has no value
-				if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
-					exprStmt->expr->accept( *visitor );
-					output << ";" << endl;
-					++i;
-					break;
-				}
-			}
-			stmt->accept( *visitor );
-			output << endl;
-			if ( wantSpacing( stmt ) ) {
-				output << endl;
-			} // if
-			++i;
-		}
-		--indent;
-		output << indent << "})";
-	}
-
-	void CodeGenerator::postvisit( ConstructorExpr * expr ) {
-		assertf( ! options.genC, "Unique expressions should not reach code generation." );
-		expr->callExpr->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( DeletedExpr * expr ) {
-		assertf( ! options.genC, "Deleted expressions should not reach code generation." );
-		expr->expr->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( DefaultArgExpr * arg ) {
-		assertf( ! options.genC, "Default argument expressions should not reach code generation." );
-		arg->expr->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( GenericExpr * expr ) {
-		assertf( ! options.genC, "C11 _Generic expressions should not reach code generation." );
-		output << "_Generic(";
-		expr->control->accept( *visitor );
-		output << ", ";
-		unsigned int numAssocs = expr->associations.size();
-		unsigned int i = 0;
-		for ( GenericExpr::Association & assoc : expr->associations ) {
-			if (assoc.isDefault) {
-				output << "default: ";
-			} else {
-				output << genType( assoc.type, "", options ) << ": ";
-			}
-			assoc.expr->accept( *visitor );
-			if ( i+1 != numAssocs ) {
-				output << ", ";
-			}
-			i++;
-		}
-		output << ")";
-	}
-
-	// *** Statements
-	void CodeGenerator::postvisit( CompoundStmt * compoundStmt ) {
-		std::list<Statement*> ks = compoundStmt->get_kids();
-		output << "{" << endl;
-
-		++indent;
-
-		for ( std::list<Statement *>::iterator i = ks.begin(); i != ks.end();  i++ ) {
-			output << indent << printLabels( (*i)->get_labels() );
-			(*i)->accept( *visitor );
-
-			output << endl;
-			if ( wantSpacing( *i ) ) {
-				output << endl;
-			} // if
-		} // for
-		--indent;
-
-		output << indent << "}";
-	}
-
-	void CodeGenerator::postvisit( ExprStmt * exprStmt ) {
-		assert( exprStmt );
-		if ( options.genC ) {
-			// cast the top-level expression to void to reduce gcc warnings.
-			exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) );
-		}
-		exprStmt->get_expr()->accept( *visitor );
-		output << ";";
-	}
-
-	void CodeGenerator::postvisit( AsmStmt * asmStmt ) {
-		output << "asm ";
-		if ( asmStmt->get_voltile() ) output << "volatile ";
-		if ( ! asmStmt->get_gotolabels().empty()  ) output << "goto ";
-		output << "( ";
-		if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor );
-		output << " : ";
-		genCommaList( asmStmt->get_output().begin(), asmStmt->get_output().end() );
-		output << " : ";
-		genCommaList( asmStmt->get_input().begin(), asmStmt->get_input().end() );
-		output << " : ";
-		genCommaList( asmStmt->get_clobber().begin(), asmStmt->get_clobber().end() );
-		if ( ! asmStmt->get_gotolabels().empty() ) {
-			output << " : ";
-			for ( std::list<Label>::iterator begin = asmStmt->get_gotolabels().begin();; ) {
-				output << *begin++;
-				if ( begin == asmStmt->get_gotolabels().end() ) break;
-				output << ", ";
-			} // for
-		} // if
-		output << " );";
-	}
-
-	void CodeGenerator::postvisit( AsmDecl * asmDecl ) {
-		output << "asm ";
-		AsmStmt * asmStmt = asmDecl->get_stmt();
-		output << "( ";
-		if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor );
-		output << " )";
-	}
-
-	void CodeGenerator::postvisit( DirectiveDecl * directiveDecl ) {
-		output << endl << directiveDecl->get_stmt()->directive;	// endl prevents spaces before directive
-	}
-
-	void CodeGenerator::postvisit( DirectiveStmt * dirStmt ) {
-		output << endl << dirStmt->directive;			// endl prevents spaces before directive
-	}
-
-	void CodeGenerator::postvisit( IfStmt * ifStmt ) {
-		output << "if ( ";
-		ifStmt->get_condition()->accept( *visitor );
-		output << " ) ";
-
-		ifStmt->get_then()->accept( *visitor );
-
-		if ( ifStmt->get_else() != 0) {
-			output << " else ";
-			ifStmt->get_else()->accept( *visitor );
-		} // if
-	}
-
-	void CodeGenerator::postvisit( SwitchStmt * switchStmt ) {
-		output << "switch ( ";
-		switchStmt->get_condition()->accept( *visitor );
-		output << " ) ";
-
-		output << "{" << endl;
-		++indent;
-		acceptAll( switchStmt->get_statements(), *visitor );
-		--indent;
-		output << indent << "}";
-	}
-
-	void CodeGenerator::postvisit( CaseStmt * caseStmt ) {
-		updateLocation( caseStmt );
-		output << indent;
-		if ( caseStmt->isDefault()) {
-			output << "default";
-		} else {
-			output << "case ";
-			caseStmt->get_condition()->accept( *visitor );
-		} // if
-		output << ":" << endl;
-
-		std::list<Statement *> sts = caseStmt->get_statements();
-
-		++indent;
-		for ( std::list<Statement *>::iterator i = sts.begin(); i != sts.end();  i++) {
-			output << indent << printLabels( (*i)->get_labels() ) ;
-			(*i)->accept( *visitor );
-			output << endl;
-		} // for
-		--indent;
-	}
-
-	void CodeGenerator::postvisit( BranchStmt * branchStmt ) {
-		switch ( branchStmt->get_type()) {
-		  case BranchStmt::Goto:
-			if ( ! branchStmt->get_target().empty() )
-				output << "goto " << branchStmt->get_target();
-			else {
-				if ( branchStmt->get_computedTarget() != 0 ) {
-					output << "goto *";
-					branchStmt->get_computedTarget()->accept( *visitor );
-				} // if
-			} // if
-			break;
-		  case BranchStmt::Break:
-			output << "break";
-			break;
-		  case BranchStmt::Continue:
-			output << "continue";
-			break;
-		  case BranchStmt::FallThrough:
-		  case BranchStmt::FallThroughDefault:
-			assertf( ! options.genC, "fallthru should not reach code generation." );
-			output << "fallthru";
-			break;
-		  default: ;									// prevent warning
-		} // switch
-		// print branch target for labelled break/continue/fallthru in debug mode
-		if ( ! options.genC && branchStmt->get_type() != BranchStmt::Goto ) {
-			if ( ! branchStmt->get_target().empty() ) {
-				output << " " << branchStmt->get_target();
-			} else if ( branchStmt->get_type() == BranchStmt::FallThrough ) {
-				output << " default";
-			}
-		}
-		output << ";";
-	}
-
-	void CodeGenerator::postvisit( ReturnStmt * returnStmt ) {
-		output << "return ";
-		maybeAccept( returnStmt->get_expr(), *visitor );
-		output << ";";
-	}
-
-	void CodeGenerator::postvisit( ThrowStmt * throwStmt ) {
-		assertf( ! options.genC, "Throw statements should not reach code generation." );
-
-		output << ((throwStmt->get_kind() == ThrowStmt::Terminate) ?
-				   "throw" : "throwResume");
-		if (throwStmt->get_expr()) {
-			output << " ";
-			throwStmt->get_expr()->accept( *visitor );
-		}
-		if (throwStmt->get_target()) {
-			output << " _At ";
-			throwStmt->get_target()->accept( *visitor );
-		}
-		output << ";";
-	}
-	void CodeGenerator::postvisit( CatchStmt * stmt ) {
-		assertf( ! options.genC, "Catch statements should not reach code generation." );
-
-		output << ((stmt->get_kind() == CatchStmt::Terminate) ?
-				   "catch" : "catchResume");
-		output << "( ";
-		stmt->decl->accept( *visitor );
-		output << " ) ";
-
-		if( stmt->cond ) {
-			output << "if/when(?) (";
-			stmt->cond->accept( *visitor );
-			output << ") ";
-		}
-		stmt->body->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( WaitForStmt * stmt ) {
-		assertf( ! options.genC, "Waitfor statements should not reach code generation." );
-
-		bool first = true;
-		for( auto & clause : stmt->clauses ) {
-			if(first) { output << "or "; first = false; }
-			if( clause.condition ) {
-				output << "when(";
-				stmt->timeout.condition->accept( *visitor );
-				output << ") ";
-			}
-			output << "waitfor(";
-			clause.target.function->accept( *visitor );
-			for( Expression * expr : clause.target.arguments ) {
-				output << ",";
-				expr->accept( *visitor );
-			}
-			output << ") ";
-			clause.statement->accept( *visitor );
-		}
-
-		if( stmt->timeout.statement ) {
-			output << "or ";
-			if( stmt->timeout.condition ) {
-				output << "when(";
-				stmt->timeout.condition->accept( *visitor );
-				output << ") ";
-			}
-			output << "timeout(";
-			stmt->timeout.time->accept( *visitor );
-			output << ") ";
-			stmt->timeout.statement->accept( *visitor );
-		}
-
-		if( stmt->orelse.statement ) {
-			output << "or ";
-			if( stmt->orelse.condition ) {
-				output << "when(";
-				stmt->orelse.condition->accept( *visitor );
-				output << ")";
-			}
-			output << "else ";
-			stmt->orelse.statement->accept( *visitor );
-		}
-	}
-
-	void CodeGenerator::postvisit( WithStmt * with ) {
-		assertf( ! options.genC, "WithStmts should not reach code generation." );
-
-		output << "with ( ";
-		genCommaList( with->exprs.begin(), with->exprs.end() );
-		output << " ) ";
-		with->stmt->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( WhileDoStmt * whileDoStmt ) {
-		if ( whileDoStmt->get_isDoWhile() ) {
-			output << "do";
-		} else {
-			output << "while (";
-			whileDoStmt->get_condition()->accept( *visitor );
-			output << ")";
-		} // if
-		output << " ";
-
-		output << CodeGenerator::printLabels( whileDoStmt->get_body()->get_labels() );
-		whileDoStmt->get_body()->accept( *visitor );
-
-		output << indent;
-
-		if ( whileDoStmt->get_isDoWhile() ) {
-			output << " while (";
-			whileDoStmt->get_condition()->accept( *visitor );
-			output << ");";
-		} // if
-	}
-
-	void CodeGenerator::postvisit( ForStmt * forStmt ) {
-		// initialization is always hoisted, so don't bother doing anything with that
-		output << "for (;";
-
-		if ( forStmt->get_condition() != 0 ) {
-			forStmt->get_condition()->accept( *visitor );
-		} // if
-		output << ";";
-
-		if ( forStmt->get_increment() != 0 ) {
-			// cast the top-level expression to void to reduce gcc warnings.
-			Expression * expr = new CastExpr( forStmt->get_increment() );
-			expr->accept( *visitor );
-		} // if
-		output << ") ";
-
-		if ( forStmt->get_body() != 0 ) {
-			output << CodeGenerator::printLabels( forStmt->get_body()->get_labels() );
-			forStmt->get_body()->accept( *visitor );
-		} // if
-	}
-
-	void CodeGenerator::postvisit( __attribute__((unused)) NullStmt * nullStmt ) {
-		//output << indent << CodeGenerator::printLabels( nullStmt->get_labels() );
-		output << "/* null statement */ ;";
-	}
-
-	void CodeGenerator::postvisit( DeclStmt * declStmt ) {
-		declStmt->get_decl()->accept( *visitor );
-
-		if ( doSemicolon( declStmt->get_decl() ) ) {
-			output << ";";
-		} // if
-	}
-
-	void CodeGenerator::postvisit( ImplicitCtorDtorStmt * stmt ) {
-		assertf( ! options.genC, "ImplicitCtorDtorStmts should not reach code generation." );
-		stmt->callStmt->accept( *visitor );
-	}
-
-	void CodeGenerator::postvisit( MutexStmt * stmt ) {
-		assertf( ! options.genC, "ImplicitCtorDtorStmts should not reach code generation." );
-		stmt->stmt->accept( *visitor );
-	}
-
-	void CodeGenerator::handleStorageClass( DeclarationWithType * decl ) {
-		if ( decl->get_storageClasses().any() ) {
-			decl->get_storageClasses().print( output );
-		} // if
-	} // CodeGenerator::handleStorageClass
-
-	std::string genName( DeclarationWithType * decl ) {
-		const OperatorInfo * opInfo = operatorLookup( decl->get_name() );
-		if ( opInfo ) {
-			return opInfo->outputName;
-		} else {
-			return decl->get_name();
-		} // if
-	}
-
-} // namespace CodeGen
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/CodeGen/CodeGenerator.h
===================================================================
--- src/CodeGen/CodeGenerator.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,198 +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.
-//
-// CodeGenerator.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed Jun 29 14:32:00 2022
-// Update Count     : 65
-//
-
-#pragma once
-
-#include <list>                   // for list
-#include <ostream>                // for ostream, operator<<
-#include <string>                 // for string
-
-#include "CodeGen/Options.h"      // for Options
-#include "Common/Indenter.h"      // for Indenter
-#include "Common/PassVisitor.h"   // for PassVisitor
-#include "SynTree/Declaration.h"  // for DeclarationWithType (ptr only), Fun...
-#include "SynTree/Visitor.h"      // for Visitor
-#include "SynTree/SynTree.h"      // for Visitor Nodes
-
-namespace ast {
-	class DeclWithType;
-}
-
-namespace CodeGen {
-	struct CodeGenerator : public WithShortCircuiting, public WithGuards, public WithVisitorRef<CodeGenerator> {
-		static int tabsize;
-
-		CodeGenerator( std::ostream &os, bool pretty = false, bool genC = false, bool lineMarks = false, bool printExprTypes = false );
-		CodeGenerator( std::ostream &os, const Options &options );
-
-		//*** Turn off visit_children for all nodes
-		void previsit( BaseSyntaxNode * );
-
-		//*** Error for unhandled node types
-		void postvisit( BaseSyntaxNode * );
-
-		//*** print type for all expressions
-		void previsit( Expression * node );
-
-		//*** Declaration
-		void postvisit( StructDecl * );
-		void postvisit( FunctionDecl * );
-		void postvisit( ObjectDecl * );
-		void postvisit( UnionDecl * aggregateDecl );
-		void postvisit( EnumDecl * aggregateDecl );
-		void postvisit( TraitDecl * aggregateDecl );
-		void postvisit( TypedefDecl * typeDecl );
-		void postvisit( TypeDecl * typeDecl );
-		void postvisit( StaticAssertDecl * assertDecl );
-
-		//*** Initializer
-		void postvisit( Designation * );
-		void postvisit( SingleInit * );
-		void postvisit( ListInit * );
-		void postvisit( ConstructorInit * );
-
-		//*** Constant
-		void postvisit( Constant * );
-
-		//*** Expression
-		void postvisit( ApplicationExpr *applicationExpr );
-		void postvisit( UntypedExpr *untypedExpr );
-		void postvisit( RangeExpr * rangeExpr );
-		void postvisit( NameExpr *nameExpr );
-		void postvisit( AddressExpr *addressExpr );
-		void postvisit( LabelAddressExpr *addressExpr );
-		void postvisit( CastExpr *castExpr );
-		void postvisit( KeywordCastExpr * castExpr );
-		void postvisit( VirtualCastExpr *castExpr );
-		void postvisit( UntypedMemberExpr *memberExpr );
-		void postvisit( MemberExpr *memberExpr );
-		void postvisit( VariableExpr *variableExpr );
-		void postvisit( ConstantExpr *constantExpr );
-		void postvisit( SizeofExpr *sizeofExpr );
-		void postvisit( AlignofExpr *alignofExpr );
-		void postvisit( UntypedOffsetofExpr *offsetofExpr );
-		void postvisit( OffsetofExpr *offsetofExpr );
-		void postvisit( OffsetPackExpr *offsetPackExpr );
-		void postvisit( LogicalExpr *logicalExpr );
-		void postvisit( ConditionalExpr *conditionalExpr );
-		void postvisit( CommaExpr *commaExpr );
-		void postvisit( CompoundLiteralExpr *compLitExpr );
-		void postvisit( UniqueExpr * );
-		void postvisit( TupleAssignExpr * tupleExpr );
-		void postvisit( UntypedTupleExpr *tupleExpr );
-		void postvisit( TupleExpr *tupleExpr );
-		void postvisit( TupleIndexExpr * tupleExpr );
-		void postvisit( TypeExpr *typeExpr );
-		void postvisit( DimensionExpr *dimensionExpr );
-		void postvisit( AsmExpr * );
-		void postvisit( StmtExpr * );
-		void postvisit( ConstructorExpr * );
-		void postvisit( DeletedExpr * );
-		void postvisit( DefaultArgExpr * );
-		void postvisit( GenericExpr * );
-
-		//*** Statements
-		void postvisit( CompoundStmt * );
-		void postvisit( ExprStmt * );
-		void postvisit( AsmStmt * );
-		void postvisit( DirectiveStmt * );
-		void postvisit( AsmDecl * );					// special: statement in declaration context
-		void postvisit( DirectiveDecl * );				// special: statement in declaration context
-		void postvisit( IfStmt * );
-		void postvisit( SwitchStmt * );
-		void postvisit( CaseStmt * );
-		void postvisit( BranchStmt * );
-		void postvisit( ReturnStmt * );
-		void postvisit( ThrowStmt * );
-		void postvisit( CatchStmt * );
-		void postvisit( WaitForStmt * );
-		void postvisit( WithStmt * );
-		void postvisit( WhileDoStmt * );
-		void postvisit( ForStmt * );
-		void postvisit( NullStmt * );
-		void postvisit( DeclStmt * );
-		void postvisit( ImplicitCtorDtorStmt * );
-		void postvisit( MutexStmt * stmt );
-
-		void genAttributes( std::list< Attribute * > & attributes );
-
-		template< class Iterator > void genCommaList( Iterator begin, Iterator end );
-
-		struct LabelPrinter {
-			LabelPrinter(CodeGenerator &cg) : cg(cg), labels( 0 ) {}
-			LabelPrinter & operator()( std::list< Label > & l );
-			CodeGenerator & cg;
-			std::list< Label > * labels;
-		};
-
-		void asmName( DeclarationWithType *decl );
-
-		void extension( Expression *expr );
-		void extension( Declaration *decl );
-
-		void updateLocation( BaseSyntaxNode const * to );
-		struct LineEnder {
-			CodeGenerator & cg;
-			LineEnder( CodeGenerator & cg ) : cg( cg ) {}
-			std::ostream & operator()(std::ostream &) const;
-		};
-	  private:
-		Indenter indent;
-		std::ostream & output;
-		LabelPrinter printLabels;
-		Options options;
-	  public:
-		LineEnder endl;
-	  private:
-
-		CodeLocation currentLocation;
-		void updateLocation( CodeLocation const & to );
-
-		void handleStorageClass( DeclarationWithType *decl );
-		void handleAggregate( AggregateDecl *aggDecl, const std::string & kind );
-		void handleTypedef( NamedTypeDecl *namedType );
-		std::string mangleName( DeclarationWithType * decl );
-	}; // CodeGenerator
-
-	template< class Iterator >
-	void CodeGenerator::genCommaList( Iterator begin, Iterator end ) {
-		if ( begin == end ) return;
-		for ( ;; ) {
-			(*begin++)->accept( *visitor );
-			if ( begin == end ) break;
-			output << ", ";								// separator
-		} // for
-	} // genCommaList
-
-	inline bool doSemicolon( Declaration* decl ) {
-		if ( FunctionDecl* func = dynamic_cast< FunctionDecl* >( decl ) ) {
-			return ! func->get_statements();
-		} // if
-		return true;
-	} // doSemicolon
-
-	/// returns C-compatible name of declaration
-	std::string genName( DeclarationWithType * decl );
-
-	inline std::ostream & operator<<( std::ostream & os, const CodeGenerator::LineEnder & endl ) {
-		return endl( os );
-	}
-} // namespace CodeGen
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/CodeGen/CodeGeneratorNew.cpp
===================================================================
--- src/CodeGen/CodeGeneratorNew.cpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/CodeGeneratorNew.cpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -24,5 +24,5 @@
 namespace CodeGen {
 
-int CodeGenerator_new::tabsize = 4;
+int CodeGenerator::tabsize = 4;
 
 // The kinds of statements that should be followed by whitespace.
@@ -35,13 +35,13 @@
 }
 
-void CodeGenerator_new::extension( ast::Expr const * expr ) {
+void CodeGenerator::extension( ast::Expr const * expr ) {
 	if ( expr->extension ) output << "__extension__ ";
 }
 
-void CodeGenerator_new::extension( ast::Decl const * decl ) {
+void CodeGenerator::extension( ast::Decl const * decl ) {
 	if ( decl->extension ) output << "__extension__ ";
 }
 
-void CodeGenerator_new::asmName( ast::DeclWithType const * decl ) {
+void CodeGenerator::asmName( ast::DeclWithType const * decl ) {
 	if ( auto asmName = decl->asmName.as<ast::ConstantExpr>() ) {
 		output << " asm ( " << asmName->rep << " )";
@@ -49,5 +49,5 @@
 }
 
-CodeGenerator_new::LabelPrinter & CodeGenerator_new::LabelPrinter::operator()(
+CodeGenerator::LabelPrinter & CodeGenerator::LabelPrinter::operator()(
 		std::vector<ast::Label> const & l ) {
 	labels = &l;
@@ -55,5 +55,5 @@
 }
 
-std::ostream & CodeGenerator_new::LabelPrinter::operator()( std::ostream & output ) const {
+std::ostream & CodeGenerator::LabelPrinter::operator()( std::ostream & output ) const {
 	const std::vector<ast::Label> & labels = *this->labels;
 	for ( const ast::Label & label : labels ) {
@@ -66,5 +66,5 @@
 // Using updateLocation at the beginning of a node and endl within a node
 // should become the method of formating.
-void CodeGenerator_new::updateLocation( CodeLocation const & to ) {
+void CodeGenerator::updateLocation( CodeLocation const & to ) {
 	// Skip if linemarks shouldn't appear or if location is unset.
 	if ( !options.lineMarks || to.isUnset() ) return;
@@ -86,9 +86,9 @@
 }
 
-void CodeGenerator_new::updateLocation( ast::ParseNode const * to ) {
+void CodeGenerator::updateLocation( ast::ParseNode const * to ) {
 	updateLocation( to->location );
 }
 
-std::ostream & CodeGenerator_new::LineEnder::operator()( std::ostream & os ) const {
+std::ostream & CodeGenerator::LineEnder::operator()( std::ostream & os ) const {
 	os << "\n" << std::flush;
 	cg.currentLocation.first_line++;
@@ -96,10 +96,10 @@
 }
 
-CodeGenerator_new::CodeGenerator_new( std::ostream & os, const Options & options ) :
-		indent( 0, CodeGenerator_new::tabsize ), output( os ),
+CodeGenerator::CodeGenerator( std::ostream & os, const Options & options ) :
+		indent( 0, CodeGenerator::tabsize ), output( os ),
 		options( options ), printLabels( *this ), endl( *this )
 {}
 
-std::string CodeGenerator_new::mangleName( ast::DeclWithType const * decl ) {
+std::string CodeGenerator::mangleName( ast::DeclWithType const * decl ) {
 	// GCC builtins should always be printed unmangled.
 	if ( options.pretty || decl->linkage.is_gcc_builtin ) {
@@ -112,5 +112,5 @@
 }
 
-void CodeGenerator_new::genAttributes(
+void CodeGenerator::genAttributes(
 		const std::vector<ast::ptr<ast::Attribute>> & attributes ) {
 	if ( attributes.empty() ) return;
@@ -129,5 +129,5 @@
 }
 
-void CodeGenerator_new::previsit( ast::Node const * ) {
+void CodeGenerator::previsit( ast::Node const * ) {
 	// All traversal is manual.
 	// TODO: Which means the ast::Pass is just providing a default no visit?
@@ -135,10 +135,10 @@
 }
 
-void CodeGenerator_new::previsit( ast::ParseNode const * node ) {
+void CodeGenerator::previsit( ast::ParseNode const * node ) {
 	previsit( (ast::Node const *)node );
 	updateLocation( node );
 }
 
-void CodeGenerator_new::postvisit( ast::Node const * node ) {
+void CodeGenerator::postvisit( ast::Node const * node ) {
 	std::stringstream ss;
 	ast::print( ss, node );
@@ -146,5 +146,5 @@
 }
 
-void CodeGenerator_new::previsit( ast::Expr const * expr ) {
+void CodeGenerator::previsit( ast::Expr const * expr ) {
 	previsit( (ast::ParseNode const *)expr );
 	GuardAction( [this, expr](){
@@ -155,5 +155,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::FunctionDecl const * decl ) {
+void CodeGenerator::postvisit( ast::FunctionDecl const * decl ) {
 	// Deleted decls should never be used, so don't print them in C.
 	if ( decl->isDeleted && options.genC ) return;
@@ -168,5 +168,5 @@
 
 	std::ostringstream acc;
-	ast::Pass<CodeGenerator_new> subCG( acc, subOptions );
+	ast::Pass<CodeGenerator> subCG( acc, subOptions );
 	// Add the forall clause.
 	// TODO: These probably should be removed by now and the assert used.
@@ -213,6 +213,5 @@
 }
 
-//void CodeGenerator_new::postvisit( ast::ObjectDecl const * decl_ ) {
-ast::ObjectDecl const * CodeGenerator_new::postvisit(
+ast::ObjectDecl const * CodeGenerator::postvisit(
 		ast::ObjectDecl const * decl ) {
 	// Deleted decls should never be used, so don't print them in C.
@@ -262,5 +261,5 @@
 }
 
-void CodeGenerator_new::handleStorageClass( ast::DeclWithType const * decl ) {
+void CodeGenerator::handleStorageClass( ast::DeclWithType const * decl ) {
 	if ( decl->storage.any() ) {
 		ast::print( output, decl->storage );
@@ -268,5 +267,5 @@
 }
 
-void CodeGenerator_new::handleAggregate(
+void CodeGenerator::handleAggregate(
 		ast::AggregateDecl const * decl, std::string const & kind ) {
 	if ( !decl->params.empty() && !options.genC ) {
@@ -296,10 +295,10 @@
 }
 
-void CodeGenerator_new::postvisit( ast::StructDecl const * decl ) {
+void CodeGenerator::postvisit( ast::StructDecl const * decl ) {
 	extension( decl );
 	handleAggregate( decl, "struct " );
 }
 
-void CodeGenerator_new::postvisit( ast::UnionDecl const * decl ) {
+void CodeGenerator::postvisit( ast::UnionDecl const * decl ) {
 	extension( decl );
 	handleAggregate( decl, "union " );
@@ -332,5 +331,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::EnumDecl const * decl ) {
+void CodeGenerator::postvisit( ast::EnumDecl const * decl ) {
 	extension( decl );
 	auto members = decl->members;
@@ -370,5 +369,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::TraitDecl const * decl ) {
+void CodeGenerator::postvisit( ast::TraitDecl const * decl ) {
 	assertf( !options.genC, "TraitDecls should not reach code generation." );
 	extension( decl );
@@ -376,10 +375,10 @@
 }
 
-void CodeGenerator_new::postvisit( ast::TypedefDecl const * decl ) {
+void CodeGenerator::postvisit( ast::TypedefDecl const * decl ) {
 	assertf( !options.genC, "Typedefs should not reach code generation." );
 	output << "typedef " << genType( decl->base, decl->name, options ) << endl;
 }
 
-void CodeGenerator_new::postvisit( ast::TypeDecl const * decl ) {
+void CodeGenerator::postvisit( ast::TypeDecl const * decl ) {
 	assertf( !options.genC, "TypeDecls should not reach code generation." );
 	output << decl->genTypeString() << " " << decl->name;
@@ -397,5 +396,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::StaticAssertDecl const * decl ) {
+void CodeGenerator::postvisit( ast::StaticAssertDecl const * decl ) {
 	output << "_Static_assert(";
 	decl->cond->accept( *visitor );
@@ -405,5 +404,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::Designation const * designation ) {
+void CodeGenerator::postvisit( ast::Designation const * designation ) {
 	auto designators = designation->designators;
 	if ( 0 == designators.size() ) return;
@@ -423,9 +422,9 @@
 }
 
-void CodeGenerator_new::postvisit( ast::SingleInit const * init ) {
+void CodeGenerator::postvisit( ast::SingleInit const * init ) {
 	init->value->accept( *visitor );
 }
 
-void CodeGenerator_new::postvisit( ast::ListInit const * init ) {
+void CodeGenerator::postvisit( ast::ListInit const * init ) {
 	auto initBegin = init->initializers.begin();
 	auto initEnd = init->initializers.end();
@@ -446,5 +445,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::ConstructorInit const * init ) {
+void CodeGenerator::postvisit( ast::ConstructorInit const * init ) {
 	assertf( !options.genC, "ConstructorInit nodes should not reach code generation." );
 	// This isn't actual code, but labels the constructor/destructor pairs.
@@ -456,5 +455,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::ApplicationExpr const * expr ) {
+void CodeGenerator::postvisit( ast::ApplicationExpr const * expr ) {
 	extension( expr );
 	if ( auto var = expr->func.as<ast::VariableExpr>() ) {
@@ -550,5 +549,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::UntypedExpr const * expr ) {
+void CodeGenerator::postvisit( ast::UntypedExpr const * expr ) {
 	extension( expr );
 	if ( auto name = expr->func.as<ast::NameExpr>() ) {
@@ -638,5 +637,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::RangeExpr const * expr ) {
+void CodeGenerator::postvisit( ast::RangeExpr const * expr ) {
 	expr->low->accept( *visitor );
 	output << " ... ";
@@ -644,5 +643,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::NameExpr const * expr ) {
+void CodeGenerator::postvisit( ast::NameExpr const * expr ) {
 	extension( expr );
 	if ( const OperatorInfo * opInfo = operatorLookup( expr->name ) ) {
@@ -657,10 +656,10 @@
 }
 
-void CodeGenerator_new::postvisit( ast::DimensionExpr const * expr ) {
+void CodeGenerator::postvisit( ast::DimensionExpr const * expr ) {
 	extension( expr );
 	output << "/*non-type*/" << expr->name;
 }
 
-void CodeGenerator_new::postvisit( ast::AddressExpr const * expr ) {
+void CodeGenerator::postvisit( ast::AddressExpr const * expr ) {
 	extension( expr );
 	output << "(&";
@@ -669,10 +668,10 @@
 }
 
-void CodeGenerator_new::postvisit( ast::LabelAddressExpr const * expr ) {
+void CodeGenerator::postvisit( ast::LabelAddressExpr const * expr ) {
 	extension( expr );
 	output << "(&&" << expr->arg << ")";
 }
 
-void CodeGenerator_new::postvisit( ast::CastExpr const * expr ) {
+void CodeGenerator::postvisit( ast::CastExpr const * expr ) {
 	extension( expr );
 	output << "(";
@@ -688,5 +687,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::KeywordCastExpr const * expr ) {
+void CodeGenerator::postvisit( ast::KeywordCastExpr const * expr ) {
 	assertf( !options.genC, "KeywordCastExpr should not reach code generation." );
 	extension( expr );
@@ -696,5 +695,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::VirtualCastExpr const * expr ) {
+void CodeGenerator::postvisit( ast::VirtualCastExpr const * expr ) {
 	assertf( !options.genC, "VirtualCastExpr should not reach code generation." );
 	extension( expr );
@@ -705,5 +704,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::UntypedMemberExpr const * expr ) {
+void CodeGenerator::postvisit( ast::UntypedMemberExpr const * expr ) {
 	assertf( !options.genC, "UntypedMemberExpr should not reach code generation." );
 	extension( expr );
@@ -713,5 +712,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::MemberExpr const * expr ) {
+void CodeGenerator::postvisit( ast::MemberExpr const * expr ) {
 	extension( expr );
 	expr->aggregate->accept( *visitor );
@@ -719,5 +718,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::VariableExpr const * expr ) {
+void CodeGenerator::postvisit( ast::VariableExpr const * expr ) {
 	extension( expr );
 	const OperatorInfo * opInfo;
@@ -733,10 +732,10 @@
 }
 
-void CodeGenerator_new::postvisit( ast::ConstantExpr const * expr ) {
+void CodeGenerator::postvisit( ast::ConstantExpr const * expr ) {
 	extension( expr );
 	output << expr->rep;
 }
 
-void CodeGenerator_new::postvisit( ast::SizeofExpr const * expr ) {
+void CodeGenerator::postvisit( ast::SizeofExpr const * expr ) {
 	extension( expr );
 	output << "sizeof(";
@@ -749,5 +748,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::AlignofExpr const * expr ) {
+void CodeGenerator::postvisit( ast::AlignofExpr const * expr ) {
 	// Using the GCC extension to avoid changing the std to C11.
 	extension( expr );
@@ -761,5 +760,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::UntypedOffsetofExpr const * expr ) {
+void CodeGenerator::postvisit( ast::UntypedOffsetofExpr const * expr ) {
 	assertf( !options.genC, "UntypedOffsetofExpr should not reach code generation." );
 	output << "offsetof(";
@@ -769,5 +768,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::OffsetofExpr const * expr ) {
+void CodeGenerator::postvisit( ast::OffsetofExpr const * expr ) {
 	// Use GCC builtin
 	output << "__builtin_offsetof(";
@@ -777,10 +776,10 @@
 }
 
-void CodeGenerator_new::postvisit( ast::OffsetPackExpr const * expr ) {
+void CodeGenerator::postvisit( ast::OffsetPackExpr const * expr ) {
 	assertf( !options.genC, "OffsetPackExpr should not reach code generation." );
 	output << "__CFA_offsetpack(" << genType( expr->type, "", options ) << ")";
 }
 
-void CodeGenerator_new::postvisit( ast::LogicalExpr const * expr ) {
+void CodeGenerator::postvisit( ast::LogicalExpr const * expr ) {
 	extension( expr );
 	output << "(";
@@ -791,5 +790,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::ConditionalExpr const * expr ) {
+void CodeGenerator::postvisit( ast::ConditionalExpr const * expr ) {
 	extension( expr );
 	output << "(";
@@ -802,5 +801,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::CommaExpr const * expr ) {
+void CodeGenerator::postvisit( ast::CommaExpr const * expr ) {
 	extension( expr );
 	output << "(";
@@ -818,10 +817,10 @@
 }
 
-void CodeGenerator_new::postvisit( ast::TupleAssignExpr const * expr ) {
+void CodeGenerator::postvisit( ast::TupleAssignExpr const * expr ) {
 	assertf( !options.genC, "TupleAssignExpr should not reach code generation." );
 	expr->stmtExpr->accept( *visitor );
 }
 
-void CodeGenerator_new::postvisit( ast::UntypedTupleExpr const * expr ) {
+void CodeGenerator::postvisit( ast::UntypedTupleExpr const * expr ) {
 	assertf( !options.genC, "UntypedTupleExpr should not reach code generation." );
 	extension( expr );
@@ -831,5 +830,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::TupleExpr const * expr ) {
+void CodeGenerator::postvisit( ast::TupleExpr const * expr ) {
 	assertf( !options.genC, "TupleExpr should not reach code generation." );
 	extension( expr );
@@ -839,5 +838,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::TupleIndexExpr const * expr ) {
+void CodeGenerator::postvisit( ast::TupleIndexExpr const * expr ) {
 	assertf( !options.genC, "TupleIndexExpr should not reach code generation." );
 	extension( expr );
@@ -846,5 +845,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::TypeExpr const * expr ) {
+void CodeGenerator::postvisit( ast::TypeExpr const * expr ) {
 	// TODO: Should there be an assertion there?
 	if ( !options.genC ) {
@@ -853,5 +852,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::AsmExpr const * expr ) {
+void CodeGenerator::postvisit( ast::AsmExpr const * expr ) {
 	if ( !expr->inout.empty() ) {
 		output << "[ " << expr->inout << " ] ";
@@ -863,5 +862,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::CompoundLiteralExpr const * expr ) {
+void CodeGenerator::postvisit( ast::CompoundLiteralExpr const * expr ) {
 	//assert( expr->result && dynamic_cast<ast::ListInit const *>( expr->init ) );
 	assert( expr->result && expr->init.as<ast::ListInit>() );
@@ -870,5 +869,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::UniqueExpr const * expr ) {
+void CodeGenerator::postvisit( ast::UniqueExpr const * expr ) {
 	assertf( !options.genC, "UniqueExpr should not reach code generation." );
 	output << "unq<" << expr->id << ">{ ";
@@ -877,5 +876,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::StmtExpr const * expr ) {
+void CodeGenerator::postvisit( ast::StmtExpr const * expr ) {
 	auto stmts = expr->stmts->kids;
 	output << "({" << endl;
@@ -905,20 +904,20 @@
 }
 
-void CodeGenerator_new::postvisit( ast::ConstructorExpr const * expr ) {
+void CodeGenerator::postvisit( ast::ConstructorExpr const * expr ) {
 	assertf( !options.genC, "ConstructorExpr should not reach code generation." );
 	expr->callExpr->accept( *visitor );
 }
 
-void CodeGenerator_new::postvisit( ast::DeletedExpr const * expr ) {
+void CodeGenerator::postvisit( ast::DeletedExpr const * expr ) {
 	assertf( !options.genC, "DeletedExpr should not reach code generation." );
 	expr->expr->accept( *visitor );
 }
 
-void CodeGenerator_new::postvisit( ast::DefaultArgExpr const * expr ) {
+void CodeGenerator::postvisit( ast::DefaultArgExpr const * expr ) {
 	assertf( !options.genC, "DefaultArgExpr should not reach code generation." );
 	expr->expr->accept( *visitor );
 }
 
-void CodeGenerator_new::postvisit( ast::GenericExpr const * expr ) {
+void CodeGenerator::postvisit( ast::GenericExpr const * expr ) {
 	assertf( !options.genC, "GenericExpr should not reach code generation." );
 	output << "_Generic(";
@@ -940,5 +939,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::CompoundStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::CompoundStmt const * stmt ) {
 	output << "{" << endl;
 
@@ -955,5 +954,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::ExprStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::ExprStmt const * stmt ) {
 	assert( stmt );
 	// Cast the top-level expression to void to reduce gcc warnings.
@@ -967,5 +966,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::AsmStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::AsmStmt const * stmt ) {
 	output << "asm ";
 	if ( stmt->isVolatile ) output << "volatile ";
@@ -991,5 +990,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::AsmDecl const * decl ) {
+void CodeGenerator::postvisit( ast::AsmDecl const * decl ) {
 	output << "asm ";
 	ast::AsmStmt const * stmt = decl->stmt;
@@ -999,15 +998,15 @@
 }
 
-void CodeGenerator_new::postvisit( ast::DirectiveDecl const * decl ) {
+void CodeGenerator::postvisit( ast::DirectiveDecl const * decl ) {
 	// endl prevents spaces before the directive.
 	output << endl << decl->stmt->directive;
 }
 
-void CodeGenerator_new::postvisit( ast::DirectiveStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::DirectiveStmt const * stmt ) {
 	// endl prevents spaces before the directive.
 	output << endl << stmt->directive;
 }
 
-void CodeGenerator_new::postvisit( ast::IfStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::IfStmt const * stmt ) {
 	output << "if ( ";
 	stmt->cond->accept( *visitor );
@@ -1022,5 +1021,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::SwitchStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::SwitchStmt const * stmt ) {
 	output << "switch ( ";
 	stmt->cond->accept( *visitor );
@@ -1036,5 +1035,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::CaseClause const * clause ) {
+void CodeGenerator::postvisit( ast::CaseClause const * clause ) {
 	updateLocation( clause );
 	output << indent;
@@ -1056,5 +1055,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::BranchStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::BranchStmt const * stmt ) {
 	switch ( stmt->kind ) {
 	case ast::BranchStmt::Goto:
@@ -1091,5 +1090,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::ReturnStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::ReturnStmt const * stmt ) {
 	output << "return ";
 	if ( stmt->expr ) stmt->expr->accept( *visitor );
@@ -1097,5 +1096,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::ThrowStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::ThrowStmt const * stmt ) {
 	assertf( !options.genC, "ThrowStmt should not reach code generation." );
 
@@ -1112,5 +1111,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::CatchClause const * stmt ) {
+void CodeGenerator::postvisit( ast::CatchClause const * stmt ) {
 	assertf( !options.genC, "CatchClause should not reach code generation." );
 
@@ -1126,5 +1125,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::WaitForStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::WaitForStmt const * stmt ) {
 	assertf( !options.genC, "WaitforStmt should not reach code generation." );
 
@@ -1172,5 +1171,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::WithStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::WithStmt const * stmt ) {
 	assertf( !options.genC, "WithStmt should not reach code generation." );
 
@@ -1181,5 +1180,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::WhileDoStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::WhileDoStmt const * stmt ) {
 	if ( stmt->isDoWhile ) {
 		output << "do";
@@ -1191,5 +1190,5 @@
 	output << " ";
 
-	output << CodeGenerator_new::printLabels( stmt->body->labels );
+	output << CodeGenerator::printLabels( stmt->body->labels );
 	stmt->body->accept( *visitor );
 
@@ -1203,5 +1202,5 @@
 }
 
-void CodeGenerator_new::postvisit( ast::ForStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::ForStmt const * stmt ) {
 	// Initializer is always hoised so don't generate it.
 	// TODO: Do an assertion check?
@@ -1226,9 +1225,9 @@
 }
 
-void CodeGenerator_new::postvisit( ast::NullStmt const * ) {
+void CodeGenerator::postvisit( ast::NullStmt const * ) {
 	output << "/* null statement */ ;";
 }
 
-void CodeGenerator_new::postvisit( ast::DeclStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::DeclStmt const * stmt ) {
 	stmt->decl->accept( *visitor );
 
@@ -1236,10 +1235,10 @@
 }
 
-void CodeGenerator_new::postvisit( ast::ImplicitCtorDtorStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::ImplicitCtorDtorStmt const * stmt ) {
 	assertf( !options.genC, "ImplicitCtorCtorStmt should not reach code generation." );
 	stmt->callStmt->accept( *visitor );
 }
 
-void CodeGenerator_new::postvisit( ast::MutexStmt const * stmt ) {
+void CodeGenerator::postvisit( ast::MutexStmt const * stmt ) {
 	assertf( !options.genC, "MutexStmt should not reach code generation." );
 	// TODO: But this isn't what a mutex statement looks like.
Index: src/CodeGen/CodeGeneratorNew.hpp
===================================================================
--- src/CodeGen/CodeGeneratorNew.hpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/CodeGeneratorNew.hpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -25,10 +25,9 @@
 namespace CodeGen {
 
-#warning Remove the _new when old version is removed.
-struct CodeGenerator_new :
+struct CodeGenerator final :
 		public ast::WithGuards,
 		public ast::WithShortCircuiting,
-		public ast::WithVisitorRef<CodeGenerator_new> {
-	CodeGenerator_new( std::ostream & out, Options const & options );
+		public ast::WithVisitorRef<CodeGenerator> {
+	CodeGenerator( std::ostream & out, Options const & options );
 
 	// Turn off visit_children for all nodes.
@@ -119,6 +118,6 @@
 	/// Custom local implementation of endl that updates print location.
 	struct LineEnder {
-		CodeGenerator_new & cg;
-		LineEnder( CodeGenerator_new & cg ) : cg( cg ) {}
+		CodeGenerator & cg;
+		LineEnder( CodeGenerator & cg ) : cg( cg ) {}
 		std::ostream & operator()( std::ostream & ) const;
 	};
@@ -129,8 +128,8 @@
 	/// Wrapper class to help print vectors of Labels.
 	struct LabelPrinter {
-		LabelPrinter( CodeGenerator_new & cg ) : cg( cg ), labels( nullptr ) {}
+		LabelPrinter( CodeGenerator & cg ) : cg( cg ), labels( nullptr ) {}
 		LabelPrinter & operator()( std::vector<ast::Label> const & l );
 		std::ostream & operator()( std::ostream & ) const;
-		CodeGenerator_new & cg;
+		CodeGenerator & cg;
 		std::vector<ast::Label> const * labels;
 	};
Index: src/CodeGen/FixMain.cc
===================================================================
--- src/CodeGen/FixMain.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/FixMain.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// FixMain.cc --
+// FixMain.cc -- Tools to change a Cforall main into a C main.
 //
 // Author           : Thierry Delisle
@@ -25,9 +25,6 @@
 #include "AST/Type.hpp"
 #include "AST/Vector.hpp"
-#include "Common/PassVisitor.h"
 #include "Common/SemanticError.h"  // for SemanticError
 #include "CodeGen/GenType.h"       // for GenType
-#include "SynTree/Declaration.h"   // for FunctionDecl, operator<<
-#include "SynTree/Type.h"          // for FunctionType
 #include "SymTab/Mangler.h"
 
@@ -36,22 +33,9 @@
 namespace {
 
-struct FindMainCore {
-	FunctionDecl * main_signature = nullptr;
-
-	void previsit( FunctionDecl * decl ) {
-		if ( FixMain::isMain( decl ) ) {
-			if ( main_signature ) {
-				SemanticError( decl, "Multiple definition of main routine\n" );
-			}
-			main_signature = decl;
-		}
-	}
-};
-
-struct FindMainCore_new {
+struct FindMainCore final {
 	ast::FunctionDecl const * main_declaration = nullptr;
 
 	void previsit( ast::FunctionDecl const * decl ) {
-		if ( FixMain::isMain( decl ) ) {
+		if ( isMain( decl ) ) {
 			if ( main_declaration ) {
 				SemanticError( decl, "Multiple definition of main routine\n" );
@@ -65,39 +49,4 @@
 	return genType( types[at], "", Options( false, false, false, false ) );
 }
-
-}
-
-	template<typename container>
-	std::string genTypeAt(const container& p, size_t idx) {
-		return genType((*std::next(p.begin(), idx))->get_type(), "");
-	}
-
-	void FixMain::fix( std::list< Declaration * > & translationUnit,
-			std::ostream &os, const char* bootloader_filename ) {
-		PassVisitor< FindMainCore > main_finder;
-		acceptAll( translationUnit, main_finder );
-		FunctionDecl * main_signature = main_finder.pass.main_signature;
-
-		if( main_signature ) {
-			os << "static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return ";
-			main_signature->mangleName = SymTab::Mangler::mangle(main_signature);
-
-			os << main_signature->get_scopedMangleName() << "(";
-			const auto& params = main_signature->get_functionType()->get_parameters();
-			switch(params.size()) {
-				case 3: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv, (" << genTypeAt(params, 2) << ")envp"; break;
-				case 2: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv"; break;
-				case 0: break;
-				default : assert(false);
-			}
-			os << "); }\n";
-
-			std::ifstream bootloader(bootloader_filename, std::ios::in);
-			assertf( bootloader.is_open(), "cannot open bootloader.c\n" );
-			os << bootloader.rdbuf();
-		}
-	}
-
-namespace {
 
 ast::ObjectDecl * makeIntObj(){
@@ -157,14 +106,17 @@
 }
 
+struct FixLinkageCore final {
+	ast::Linkage::Spec const spec;
+	FixLinkageCore( ast::Linkage::Spec spec ) : spec( spec ) {}
+
+	ast::FunctionDecl const * previsit( ast::FunctionDecl const * decl ) {
+		if ( decl->name != "main" ) return decl;
+		return ast::mutate_field( decl, &ast::FunctionDecl::linkage, spec );
+	}
+};
+
 } // namespace
 
-bool FixMain::isMain( FunctionDecl * decl ) {
-	if ( std::string("main") != decl->name ) {
-		return false;
-	}
-	return is_main( SymTab::Mangler::mangle( decl, true, true ) );
-}
-
-bool FixMain::isMain( const ast::FunctionDecl * decl ) {
+bool isMain( const ast::FunctionDecl * decl ) {
 	if ( std::string("main") != decl->name ) {
 		return false;
@@ -173,8 +125,15 @@
 }
 
-void FixMain::fix( ast::TranslationUnit & translationUnit,
+void fixMainLinkage( ast::TranslationUnit & translationUnit,
+		bool replace_main ) {
+	ast::Linkage::Spec const spec =
+		( replace_main ) ? ast::Linkage::Cforall : ast::Linkage::C;
+	ast::Pass<FixLinkageCore>::run( translationUnit, spec );
+}
+
+void fixMainInvoke( ast::TranslationUnit & translationUnit,
 		std::ostream &os, const char * bootloader_filename ) {
 
-	ast::Pass<FindMainCore_new> main_finder;
+	ast::Pass<FindMainCore> main_finder;
 	ast::accept_all( translationUnit, main_finder );
 	if ( nullptr == main_finder.core.main_declaration ) return;
Index: src/CodeGen/FixMain.h
===================================================================
--- src/CodeGen/FixMain.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/FixMain.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// FixMain.h -- 
+// FixMain.h -- Tools to change a Cforall main into a C main.
 //
 // Author           : Thierry Delisle
@@ -17,12 +17,5 @@
 
 #include <iosfwd>
-#include <memory>
-#include <list>
 
-#include "AST/LinkageSpec.hpp"
-#include "SynTree/LinkageSpec.h"
-
-class Declaration;
-class FunctionDecl;
 namespace ast {
 	class FunctionDecl;
@@ -32,28 +25,13 @@
 namespace CodeGen {
 
-class FixMain {
-public :
-	static inline LinkageSpec::Spec mainLinkage() {
-		return replace_main ? LinkageSpec::Cforall : LinkageSpec::C;
-	}
-	static inline ast::Linkage::Spec getMainLinkage() {
-		return replace_main ? ast::Linkage::Cforall : ast::Linkage::C;
-	}
+/// Is this function a program main function?
+bool isMain( const ast::FunctionDecl * decl );
 
-	static inline void setReplaceMain(bool val) {
-		replace_main = val;
-	}
+/// Adjust the linkage of main functions.
+void fixMainLinkage( ast::TranslationUnit & transUnit, bool replaceMain );
 
-	static bool isMain(FunctionDecl* decl);
-	static bool isMain(const ast::FunctionDecl * decl);
-
-	static void fix( std::list< Declaration * > & decls,
-			std::ostream &os, const char* bootloader_filename );
-	static void fix( ast::TranslationUnit & translationUnit,
-			std::ostream &os, const char * bootloader_filename );
-
-private:
-	static bool replace_main;
-};
+/// Add a wrapper around to run the Cforall main.
+void fixMainInvoke( ast::TranslationUnit & transUnit,
+		std::ostream & os, const char * bootloaderFilename );
 
 } // namespace CodeGen
Index: c/CodeGen/FixMain2.cc
===================================================================
--- src/CodeGen/FixMain2.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,28 +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.
-//
-// FixMain2.cc -- A side file used to seperate the compiler and demangler.
-//
-// Author           : Andrew Beach
-// Created On       : Tue May 17 10:05:00 2022
-// Last Modified By : Andrew Beach
-// Last Modified On : Tue May 17 10:08:00 2022
-// Update Count     : 0
-//
-
-#include "FixMain.h"
-
-namespace CodeGen {
-
-bool FixMain::replace_main = false;
-
-} // namespace CodeGen
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/CodeGen/FixNames.cc
===================================================================
--- src/CodeGen/FixNames.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/FixNames.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -22,70 +22,15 @@
 #include "AST/Expr.hpp"
 #include "AST/Pass.hpp"
-#include "Common/PassVisitor.h"
 #include "Common/SemanticError.h"  // for SemanticError
 #include "FixMain.h"               // for FixMain
 #include "SymTab/Mangler.h"        // for Mangler
-#include "SynTree/LinkageSpec.h"   // for Cforall, isMangled
-#include "SynTree/Constant.h"      // for Constant
-#include "SynTree/Declaration.h"   // for FunctionDecl, ObjectDecl, Declarat...
-#include "SynTree/Expression.h"    // for ConstantExpr
-#include "SynTree/Label.h"         // for Label, noLabels
-#include "SynTree/Statement.h"     // for ReturnStmt, CompoundStmt
-#include "SynTree/Type.h"          // for Type, BasicType, Type::Qualifiers
-#include "SynTree/Visitor.h"       // for Visitor, acceptAll
 #include "CompilationState.h"
 
 namespace CodeGen {
-	class FixNames : public WithGuards {
-	  public:
-		void postvisit( ObjectDecl *objectDecl );
-		void postvisit( FunctionDecl *functionDecl );
 
-		void previsit( CompoundStmt *compoundStmt );
-	  private:
-		int scopeLevel = 1;
-
-		void fixDWT( DeclarationWithType *dwt );
-	};
-
-	void fixNames( std::list< Declaration* > & translationUnit ) {
-		PassVisitor<FixNames> fixer;
-		acceptAll( translationUnit, fixer );
-	}
-
-	void FixNames::fixDWT( DeclarationWithType * dwt ) {
-		if ( dwt->get_name() != "" ) {
-			if ( LinkageSpec::isMangled( dwt->get_linkage() ) ) {
-				if (!useNewAST) {
-					dwt->set_mangleName( SymTab::Mangler::mangle( dwt ) );
-				}
-				dwt->set_scopeLevel( scopeLevel );
-			} // if
-		} // if
-	}
-
-	void FixNames::postvisit( ObjectDecl * objectDecl ) {
-		fixDWT( objectDecl );
-	}
-
-	void FixNames::postvisit( FunctionDecl * functionDecl ) {
-		fixDWT( functionDecl );
-
-		if ( FixMain::isMain( functionDecl ) ) {
-			int nargs = functionDecl->get_functionType()->get_parameters().size();
-			if( !(nargs == 0 || nargs == 2 || nargs == 3) ) {
-				SemanticError(functionDecl, "Main expected to have 0, 2 or 3 arguments\n");
-			}
-			functionDecl->get_statements()->get_kids().push_back( new ReturnStmt( new ConstantExpr( Constant::from_int( 0 ) ) ) );
-		}
-	}
-
-	void FixNames::previsit( CompoundStmt * ) {
-		scopeLevel++;
-		GuardAction( [this](){ scopeLevel--; } );
-	}
+namespace {
 
 /// Does work with the main function and scopeLevels.
-class FixNames_new final {
+class FixNames final {
 	int scopeLevel = 1;
 
@@ -103,5 +48,5 @@
 
 	const ast::FunctionDecl *postvisit( const ast::FunctionDecl *functionDecl ) {
-		if ( FixMain::isMain( functionDecl ) ) {
+		if ( isMain( functionDecl ) ) {
 			auto mutDecl = ast::mutate( functionDecl );
 
@@ -138,6 +83,8 @@
 };
 
+} // namespace
+
 void fixNames( ast::TranslationUnit & translationUnit ) {
-	ast::Pass<FixNames_new>::run( translationUnit );
+	ast::Pass<FixNames>::run( translationUnit );
 }
 
Index: src/CodeGen/FixNames.h
===================================================================
--- src/CodeGen/FixNames.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/FixNames.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,7 +16,4 @@
 #pragma once
 
-#include <list>  // for list
-
-class Declaration;
 namespace ast {
 	class TranslationUnit;
@@ -24,8 +21,8 @@
 
 namespace CodeGen {
-	/// mangles object and function names
-	void fixNames( std::list< Declaration* > & translationUnit );
+
 /// Sets scope levels and fills in main's default return.
 void fixNames( ast::TranslationUnit & translationUnit );
+
 } // namespace CodeGen
 
Index: src/CodeGen/GenType.cc
===================================================================
--- src/CodeGen/GenType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/GenType.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -21,347 +21,16 @@
 #include "AST/Print.hpp"          // for print
 #include "AST/Vector.hpp"         // for vector
-#include "CodeGenerator.h"        // for CodeGenerator
-#include "CodeGeneratorNew.hpp"   // for CodeGenerator_new
-#include "SynTree/Declaration.h"  // for DeclarationWithType
-#include "SynTree/Expression.h"   // for Expression
-#include "SynTree/Type.h"         // for PointerType, Type, FunctionType
-#include "SynTree/Visitor.h"      // for Visitor
+#include "CodeGeneratorNew.hpp"   // for CodeGenerator
+#include "Common/UniqueName.h"    // for UniqueName
 
 namespace CodeGen {
-	struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting {
-		std::string typeString;
-		GenType( const std::string &typeString, const Options &options );
-
-		void previsit( BaseSyntaxNode * );
-		void postvisit( BaseSyntaxNode * );
-
-		void postvisit( FunctionType * funcType );
-		void postvisit( VoidType * voidType );
-		void postvisit( BasicType * basicType );
-		void postvisit( PointerType * pointerType );
-		void postvisit( ArrayType * arrayType );
-		void postvisit( ReferenceType * refType );
-		void postvisit( StructInstType * structInst );
-		void postvisit( UnionInstType * unionInst );
-		void postvisit( EnumInstType * enumInst );
-		void postvisit( TypeInstType * typeInst );
-		void postvisit( TupleType  * tupleType );
-		void postvisit( VarArgsType * varArgsType );
-		void postvisit( ZeroType * zeroType );
-		void postvisit( OneType * oneType );
-		void postvisit( GlobalScopeType * globalType );
-		void postvisit( TraitInstType * inst );
-		void postvisit( TypeofType * typeof );
-		void postvisit( VTableType * vtable );
-		void postvisit( QualifiedType * qualType );
-
-	  private:
-		void handleQualifiers( Type *type );
-		std::string handleGeneric( ReferenceToType * refType );
-		void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic );
-
-		Options options;
-	};
-
-	std::string genType( Type *type, const std::string &baseString, const Options &options ) {
-		PassVisitor<GenType> gt( baseString, options );
-		std::ostringstream os;
-
-		if ( ! type->get_attributes().empty() ) {
-			PassVisitor<CodeGenerator> cg( os, options );
-			cg.pass.genAttributes( type->get_attributes() );
-		} // if
-
-		type->accept( gt );
-		return os.str() + gt.pass.typeString;
-	}
-
-	std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) {
-		return genType( type, baseString, Options(pretty, genC, lineMarks, false ) );
-	}
-
-	std::string genPrettyType( Type * type, const std::string & baseString ) {
-		return genType( type, baseString, true, false );
-	}
-
-	GenType::GenType( const std::string &typeString, const Options &options ) : typeString( typeString ), options( options ) {}
-
-	// *** BaseSyntaxNode
-	void GenType::previsit( BaseSyntaxNode * ) {
-		// turn off automatic recursion for all nodes, to allow each visitor to
-		// precisely control the order in which its children are visited.
-		visit_children = false;
-	}
-
-	void GenType::postvisit( BaseSyntaxNode * node ) {
-		std::stringstream ss;
-		node->print( ss );
-		assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() );
-	}
-
-	void GenType::postvisit( VoidType * voidType ) {
-		typeString = "void " + typeString;
-		handleQualifiers( voidType );
-	}
-
-	void GenType::postvisit( BasicType * basicType ) {
-		BasicType::Kind kind = basicType->kind;
-		assert( 0 <= kind && kind < BasicType::NUMBER_OF_BASIC_TYPES );
-		typeString = std::string( BasicType::typeNames[kind] ) + " " + typeString;
-		handleQualifiers( basicType );
-	}
-
-	void GenType::genArray( const Type::Qualifiers & qualifiers, Type * base, Expression *dimension, bool isVarLen, bool isStatic ) {
-		std::ostringstream os;
-		if ( typeString != "" ) {
-			if ( typeString[ 0 ] == '*' ) {
-				os << "(" << typeString << ")";
-			} else {
-				os << typeString;
-			} // if
-		} // if
-		os << "[";
-
-		if ( isStatic ) {
-			os << "static ";
-		} // if
-		if ( qualifiers.is_const ) {
-			os << "const ";
-		} // if
-		if ( qualifiers.is_volatile ) {
-			os << "volatile ";
-		} // if
-		if ( qualifiers.is_restrict ) {
-			os << "__restrict ";
-		} // if
-		if ( qualifiers.is_atomic ) {
-			os << "_Atomic ";
-		} // if
-		if ( dimension != 0 ) {
-			PassVisitor<CodeGenerator> cg( os, options );
-			dimension->accept( cg );
-		} else if ( isVarLen ) {
-			// no dimension expression on a VLA means it came in with the * token
-			os << "*";
-		} // if
-		os << "]";
-
-		typeString = os.str();
-
-		base->accept( *visitor );
-	}
-
-	void GenType::postvisit( PointerType * pointerType ) {
-		assert( pointerType->base != 0);
-		if ( pointerType->get_isStatic() || pointerType->get_isVarLen() || pointerType->dimension ) {
-			genArray( pointerType->get_qualifiers(), pointerType->base, pointerType->dimension, pointerType->get_isVarLen(), pointerType->get_isStatic() );
-		} else {
-			handleQualifiers( pointerType );
-			if ( typeString[ 0 ] == '?' ) {
-				typeString = "* " + typeString;
-			} else {
-				typeString = "*" + typeString;
-			} // if
-			pointerType->base->accept( *visitor );
-		} // if
-	}
-
-	void GenType::postvisit( ArrayType * arrayType ) {
-		genArray( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->get_isVarLen(), arrayType->get_isStatic() );
-	}
-
-	void GenType::postvisit( ReferenceType * refType ) {
-		assert( 0 != refType->base );
-		assertf( ! options.genC, "Reference types should not reach code generation." );
-		handleQualifiers( refType );
-		typeString = "&" + typeString;
-		refType->base->accept( *visitor );
-	}
-
-	void GenType::postvisit( FunctionType * funcType ) {
-		std::ostringstream os;
-
-		if ( typeString != "" ) {
-			if ( typeString[ 0 ] == '*' ) {
-				os << "(" << typeString << ")";
-			} else {
-				os << typeString;
-			} // if
-		} // if
-
-		/************* parameters ***************/
-
-		const std::list<DeclarationWithType *> &pars = funcType->parameters;
-
-		if ( pars.empty() ) {
-			if ( funcType->get_isVarArgs() ) {
-				os << "()";
-			} else {
-				os << "(void)";
-			} // if
-		} else {
-			PassVisitor<CodeGenerator> cg( os, options );
-			os << "(" ;
-
-			cg.pass.genCommaList( pars.begin(), pars.end() );
-
-			if ( funcType->get_isVarArgs() ) {
-				os << ", ...";
-			} // if
-			os << ")";
-		} // if
-
-		typeString = os.str();
-
-		if ( funcType->returnVals.size() == 0 ) {
-			typeString = "void " + typeString;
-		} else {
-			funcType->returnVals.front()->get_type()->accept( *visitor );
-		} // if
-
-		// add forall
-		if( ! funcType->forall.empty() && ! options.genC ) {
-			// assertf( ! genC, "Aggregate type parameters should not reach code generation." );
-			std::ostringstream os;
-			PassVisitor<CodeGenerator> cg( os, options );
-			os << "forall(";
-			cg.pass.genCommaList( funcType->forall.begin(), funcType->forall.end() );
-			os << ")" << std::endl;
-			typeString = os.str() + typeString;
-		}
-	}
-
-	std::string GenType::handleGeneric( ReferenceToType * refType ) {
-		if ( ! refType->parameters.empty() ) {
-			std::ostringstream os;
-			PassVisitor<CodeGenerator> cg( os, options );
-			os << "(";
-			cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() );
-			os << ") ";
-			return os.str();
-		}
-		return "";
-	}
-
-	void GenType::postvisit( StructInstType * structInst )  {
-		typeString = structInst->name + handleGeneric( structInst ) + " " + typeString;
-		if ( options.genC ) typeString = "struct " + typeString;
-		handleQualifiers( structInst );
-	}
-
-	void GenType::postvisit( UnionInstType * unionInst ) {
-		typeString = unionInst->name + handleGeneric( unionInst ) + " " + typeString;
-		if ( options.genC ) typeString = "union " + typeString;
-		handleQualifiers( unionInst );
-	}
-
-	void GenType::postvisit( EnumInstType * enumInst ) {
-		if ( enumInst->baseEnum && enumInst->baseEnum->base ) {
-			typeString = genType(enumInst->baseEnum->base, typeString, options);
-		} else {
-			typeString = enumInst->name + " " + typeString;
-			if ( options.genC ) {
-				typeString = "enum " + typeString;
-			}
-		}
-		handleQualifiers( enumInst );
-	}
-
-	void GenType::postvisit( TypeInstType * typeInst ) {
-		assertf( ! options.genC, "Type instance types should not reach code generation." );
-		typeString = typeInst->name + " " + typeString;
-		handleQualifiers( typeInst );
-	}
-
-	void GenType::postvisit( TupleType * tupleType ) {
-		assertf( ! options.genC, "Tuple types should not reach code generation." );
-		unsigned int i = 0;
-		std::ostringstream os;
-		os << "[";
-		for ( Type * t : *tupleType ) {
-			i++;
-			os << genType( t, "", options ) << (i == tupleType->size() ? "" : ", ");
-		}
-		os << "] ";
-		typeString = os.str() + typeString;
-	}
-
-	void GenType::postvisit( VarArgsType * varArgsType ) {
-		typeString = "__builtin_va_list " + typeString;
-		handleQualifiers( varArgsType );
-	}
-
-	void GenType::postvisit( ZeroType * zeroType ) {
-		// ideally these wouldn't hit codegen at all, but should be safe to make them ints
-		typeString = (options.pretty ? "zero_t " : "long int ") + typeString;
-		handleQualifiers( zeroType );
-	}
-
-	void GenType::postvisit( OneType * oneType ) {
-		// ideally these wouldn't hit codegen at all, but should be safe to make them ints
-		typeString = (options.pretty ? "one_t " : "long int ") + typeString;
-		handleQualifiers( oneType );
-	}
-
-	void GenType::postvisit( GlobalScopeType * globalType ) {
-		assertf( ! options.genC, "Global scope type should not reach code generation." );
-		handleQualifiers( globalType );
-	}
-
-	void GenType::postvisit( TraitInstType * inst ) {
-		assertf( ! options.genC, "Trait types should not reach code generation." );
-		typeString = inst->name + " " + typeString;
-		handleQualifiers( inst );
-	}
-
-	void GenType::postvisit( TypeofType * typeof ) {
-		std::ostringstream os;
-		PassVisitor<CodeGenerator> cg( os, options );
-		os << "typeof(";
-		typeof->expr->accept( cg );
-		os << ") " << typeString;
-		typeString = os.str();
-		handleQualifiers( typeof );
-	}
-
-	void GenType::postvisit( VTableType * vtable ) {
-		assertf( ! options.genC, "Virtual table types should not reach code generation." );
-		std::ostringstream os;
-		os << "vtable(" << genType( vtable->base, "", options ) << ") " << typeString;
-		typeString = os.str();
-		handleQualifiers( vtable );
-	}
-
-	void GenType::postvisit( QualifiedType * qualType ) {
-		assertf( ! options.genC, "Qualified types should not reach code generation." );
-		std::ostringstream os;
-		os << genType( qualType->parent, "", options ) << "." << genType( qualType->child, "", options ) << typeString;
-		typeString = os.str();
-		handleQualifiers( qualType );
-	}
-
-	void GenType::handleQualifiers( Type * type ) {
-		if ( type->get_const() ) {
-			typeString = "const " + typeString;
-		} // if
-		if ( type->get_volatile() ) {
-			typeString = "volatile " + typeString;
-		} // if
-		if ( type->get_restrict() ) {
-			typeString = "__restrict " + typeString;
-		} // if
-		if ( type->get_atomic() ) {
-			typeString = "_Atomic " + typeString;
-		} // if
-	}
 
 namespace {
 
-#warning Remove the _new when old version is removed.
-struct GenType_new :
+struct GenType final :
 		public ast::WithShortCircuiting,
-		public ast::WithVisitorRef<GenType_new> {
+		public ast::WithVisitorRef<GenType> {
 	std::string result;
-	GenType_new( const std::string &typeString, const Options &options );
+	GenType( const std::string &typeString, const Options &options );
 
 	void previsit( ast::Node const * );
@@ -397,7 +66,7 @@
 };
 
-GenType_new::GenType_new( const std::string &typeString, const Options &options ) : result( typeString ), options( options ) {}
-
-void GenType_new::previsit( ast::Node const * ) {
+GenType::GenType( const std::string &typeString, const Options &options ) : result( typeString ), options( options ) {}
+
+void GenType::previsit( ast::Node const * ) {
 	// Turn off automatic recursion for all nodes, to allow each visitor to
 	// precisely control the order in which its children are visited.
@@ -405,5 +74,5 @@
 }
 
-void GenType_new::postvisit( ast::Node const * node ) {
+void GenType::postvisit( ast::Node const * node ) {
 	std::stringstream ss;
 	ast::print( ss, node );
@@ -411,10 +80,10 @@
 }
 
-void GenType_new::postvisit( ast::VoidType const * type ) {
+void GenType::postvisit( ast::VoidType const * type ) {
 	result = "void " + result;
 	handleQualifiers( type );
 }
 
-void GenType_new::postvisit( ast::BasicType const * type ) {
+void GenType::postvisit( ast::BasicType const * type ) {
 	ast::BasicType::Kind kind = type->kind;
 	assert( 0 <= kind && kind < ast::BasicType::NUMBER_OF_BASIC_TYPES );
@@ -423,5 +92,5 @@
 }
 
-void GenType_new::genArray( const ast::CV::Qualifiers & qualifiers, ast::Type const * base, ast::Expr const *dimension, bool isVarLen, bool isStatic ) {
+void GenType::genArray( const ast::CV::Qualifiers & qualifiers, ast::Type const * base, ast::Expr const *dimension, bool isVarLen, bool isStatic ) {
 	std::ostringstream os;
 	if ( result != "" ) {
@@ -449,5 +118,5 @@
 	}
 	if ( dimension != 0 ) {
-		ast::Pass<CodeGenerator_new>::read( dimension, os, options );
+		ast::Pass<CodeGenerator>::read( dimension, os, options );
 	} else if ( isVarLen ) {
 		// no dimension expression on a VLA means it came in with the * token
@@ -461,5 +130,5 @@
 }
 
-void GenType_new::postvisit( ast::PointerType const * type ) {
+void GenType::postvisit( ast::PointerType const * type ) {
 	if ( type->isStatic || type->isVarLen || type->dimension ) {
 		genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic );
@@ -475,9 +144,9 @@
 }
 
-void GenType_new::postvisit( ast::ArrayType const * type ) {
+void GenType::postvisit( ast::ArrayType const * type ) {
 	genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic );
 }
 
-void GenType_new::postvisit( ast::ReferenceType const * type ) {
+void GenType::postvisit( ast::ReferenceType const * type ) {
 	assertf( !options.genC, "Reference types should not reach code generation." );
 	handleQualifiers( type );
@@ -486,5 +155,5 @@
 }
 
-void GenType_new::postvisit( ast::FunctionType const * type ) {
+void GenType::postvisit( ast::FunctionType const * type ) {
 	std::ostringstream os;
 
@@ -526,5 +195,5 @@
 		//assertf( !options.genC, "FunctionDecl type parameters should not reach code generation." );
 		std::ostringstream os;
-		ast::Pass<CodeGenerator_new> cg( os, options );
+		ast::Pass<CodeGenerator> cg( os, options );
 		os << "forall(";
 		cg.core.genCommaList( type->forall );
@@ -534,8 +203,8 @@
 }
 
-std::string GenType_new::handleGeneric( ast::BaseInstType const * type ) {
+std::string GenType::handleGeneric( ast::BaseInstType const * type ) {
 	if ( !type->params.empty() ) {
 		std::ostringstream os;
-		ast::Pass<CodeGenerator_new> cg( os, options );
+		ast::Pass<CodeGenerator> cg( os, options );
 		os << "(";
 		cg.core.genCommaList( type->params );
@@ -546,5 +215,5 @@
 }
 
-void GenType_new::postvisit( ast::StructInstType const * type )  {
+void GenType::postvisit( ast::StructInstType const * type )  {
 	result = type->name + handleGeneric( type ) + " " + result;
 	if ( options.genC ) result = "struct " + result;
@@ -552,5 +221,5 @@
 }
 
-void GenType_new::postvisit( ast::UnionInstType const * type ) {
+void GenType::postvisit( ast::UnionInstType const * type ) {
 	result = type->name + handleGeneric( type ) + " " + result;
 	if ( options.genC ) result = "union " + result;
@@ -558,5 +227,5 @@
 }
 
-void GenType_new::postvisit( ast::EnumInstType const * type ) {
+void GenType::postvisit( ast::EnumInstType const * type ) {
 	if ( type->base && type->base->base ) {
 		result = genType( type->base->base, result, options );
@@ -570,5 +239,5 @@
 }
 
-void GenType_new::postvisit( ast::TypeInstType const * type ) {
+void GenType::postvisit( ast::TypeInstType const * type ) {
 	assertf( !options.genC, "TypeInstType should not reach code generation." );
 	result = type->name + " " + result;
@@ -576,5 +245,5 @@
 }
 
-void GenType_new::postvisit( ast::TupleType const * type ) {
+void GenType::postvisit( ast::TupleType const * type ) {
 	assertf( !options.genC, "TupleType should not reach code generation." );
 	unsigned int i = 0;
@@ -589,10 +258,10 @@
 }
 
-void GenType_new::postvisit( ast::VarArgsType const * type ) {
+void GenType::postvisit( ast::VarArgsType const * type ) {
 	result = "__builtin_va_list " + result;
 	handleQualifiers( type );
 }
 
-void GenType_new::postvisit( ast::ZeroType const * type ) {
+void GenType::postvisit( ast::ZeroType const * type ) {
 	// Ideally these wouldn't hit codegen at all, but should be safe to make them ints.
 	result = (options.pretty ? "zero_t " : "long int ") + result;
@@ -600,5 +269,5 @@
 }
 
-void GenType_new::postvisit( ast::OneType const * type ) {
+void GenType::postvisit( ast::OneType const * type ) {
 	// Ideally these wouldn't hit codegen at all, but should be safe to make them ints.
 	result = (options.pretty ? "one_t " : "long int ") + result;
@@ -606,10 +275,10 @@
 }
 
-void GenType_new::postvisit( ast::GlobalScopeType const * type ) {
+void GenType::postvisit( ast::GlobalScopeType const * type ) {
 	assertf( !options.genC, "GlobalScopeType should not reach code generation." );
 	handleQualifiers( type );
 }
 
-void GenType_new::postvisit( ast::TraitInstType const * type ) {
+void GenType::postvisit( ast::TraitInstType const * type ) {
 	assertf( !options.genC, "TraitInstType should not reach code generation." );
 	result = type->name + " " + result;
@@ -617,8 +286,8 @@
 }
 
-void GenType_new::postvisit( ast::TypeofType const * type ) {
+void GenType::postvisit( ast::TypeofType const * type ) {
 	std::ostringstream os;
 	os << "typeof(";
-	ast::Pass<CodeGenerator_new>::read( type, os, options );
+	ast::Pass<CodeGenerator>::read( type, os, options );
 	os << ") " << result;
 	result = os.str();
@@ -626,5 +295,5 @@
 }
 
-void GenType_new::postvisit( ast::VTableType const * type ) {
+void GenType::postvisit( ast::VTableType const * type ) {
 	assertf( !options.genC, "Virtual table types should not reach code generation." );
 	std::ostringstream os;
@@ -634,5 +303,5 @@
 }
 
-void GenType_new::postvisit( ast::QualifiedType const * type ) {
+void GenType::postvisit( ast::QualifiedType const * type ) {
 	assertf( !options.genC, "QualifiedType should not reach code generation." );
 	std::ostringstream os;
@@ -642,5 +311,5 @@
 }
 
-void GenType_new::handleQualifiers( ast::Type const * type ) {
+void GenType::handleQualifiers( ast::Type const * type ) {
 	if ( type->is_const() ) {
 		result = "const " + result;
@@ -657,11 +326,12 @@
 }
 
-std::string GenType_new::genParamList( const ast::vector<ast::Type> & range ) {
+std::string GenType::genParamList( const ast::vector<ast::Type> & range ) {
 	auto cur = range.begin();
 	auto end = range.end();
 	if ( cur == end ) return "";
 	std::ostringstream oss;
-	for ( unsigned int i = 0 ; ; ++i ) {
-		oss << genType( *cur++, "__param_" + std::to_string(i), options );
+	UniqueName param( "__param_" );
+	while ( true ) {
+		oss << genType( *cur++, options.genC ? param.newName() : "", options );
 		if ( cur == end ) break;
 		oss << ", ";
@@ -675,13 +345,13 @@
 	std::ostringstream os;
 	if ( !type->attributes.empty() ) {
-		ast::Pass<CodeGenerator_new> cg( os, options );
+		ast::Pass<CodeGenerator> cg( os, options );
 		cg.core.genAttributes( type->attributes );
 	}
 
-	return os.str() + ast::Pass<GenType_new>::read( type, base, options );
+	return os.str() + ast::Pass<GenType>::read( type, base, options );
 }
 
 std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options ) {
-	return ast::Pass<GenType_new>::read( type, base, options );
+	return ast::Pass<GenType>::read( type, base, options );
 }
 
Index: src/CodeGen/Generate.cc
===================================================================
--- src/CodeGen/Generate.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/Generate.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -19,79 +19,10 @@
 #include <string>                    // for operator<<
 
-#include "CodeGeneratorNew.hpp"      // for CodeGenerator_new, doSemicolon, ...
-#include "CodeGenerator.h"           // for CodeGenerator, doSemicolon, oper...
+#include "CodeGeneratorNew.hpp"      // for CodeGenerator, doSemicolon, ...
 #include "GenType.h"                 // for genPrettyType
-#include "Common/PassVisitor.h"      // for PassVisitor
-#include "SynTree/LinkageSpec.h"     // for isBuiltin, isGeneratable
-#include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
-#include "SynTree/Declaration.h"     // for Declaration
-#include "SynTree/Type.h"            // for Type
 
 using namespace std;
 
 namespace CodeGen {
-	namespace {
-		/// Removes misc. nodes that should not exist in CodeGen
-		struct TreeCleaner {
-			void premutate( CompoundStmt * stmt );
-			Statement * postmutate( ImplicitCtorDtorStmt * stmt );
-
-			static bool shouldClean( Declaration * );
-		};
-
-		void cleanTree( std::list< Declaration * > & translationUnit ) {
-			PassVisitor<TreeCleaner> cleaner;
-			filter( translationUnit, [](Declaration * decl) { return TreeCleaner::shouldClean(decl); }, false );
-			mutateAll( translationUnit, cleaner );
-		} // cleanTree
-	} // namespace
-
-	void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC, bool lineMarks, bool printExprTypes ) {
-		cleanTree( translationUnit );
-
-		PassVisitor<CodeGenerator> cgv( os, pretty, generateC, lineMarks, printExprTypes );
-		for ( auto & dcl : translationUnit ) {
-			if ( LinkageSpec::isGeneratable( dcl->get_linkage() ) && (doIntrinsics || ! LinkageSpec::isBuiltin( dcl->get_linkage() ) ) ) {
-				cgv.pass.updateLocation( dcl );
-				dcl->accept(cgv);
-				if ( doSemicolon( dcl ) ) {
-					os << ";";
-				} // if
-				os << cgv.pass.endl;
-			} // if
-		} // for
-	}
-
-	void generate( BaseSyntaxNode * node, std::ostream & os ) {
-		if ( Type * type = dynamic_cast< Type * >( node ) ) {
-			os << genPrettyType( type, "" );
-		} else {
-			PassVisitor<CodeGenerator> cgv( os, true, false, false, false );
-			node->accept( cgv );
-		}
-		os << std::endl;
-	}
-
-	namespace {
-		void TreeCleaner::premutate( CompoundStmt * cstmt ) {
-			filter( cstmt->kids, [](Statement * stmt) {
-				if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
-					return shouldClean( declStmt->decl );
-				}
-				return false;
-			}, false );
-		}
-
-		Statement * TreeCleaner::postmutate( ImplicitCtorDtorStmt * stmt ) {
-			Statement * callStmt = nullptr;
-			std::swap( stmt->callStmt, callStmt );
-			delete stmt;
-			return callStmt;
-		}
-
-		bool TreeCleaner::shouldClean( Declaration * decl ) {
-			return dynamic_cast< TraitDecl * >( decl );
-		}
-	} // namespace
 
 namespace {
@@ -101,5 +32,5 @@
 
 	/// Removes various nodes that should not exist in CodeGen.
-	struct TreeCleaner_new {
+	struct TreeCleaner final {
 		ast::CompoundStmt const * previsit( ast::CompoundStmt const * stmt ) {
 			auto mutStmt = ast::mutate( stmt );
@@ -120,7 +51,7 @@
 		bool pretty, bool generateC, bool lineMarks, bool printExprTypes ) {
 	erase_if( translationUnit.decls, shouldClean );
-	ast::Pass<TreeCleaner_new>::run( translationUnit );
+	ast::Pass<TreeCleaner>::run( translationUnit );
 
-	ast::Pass<CodeGenerator_new> cgv( os,
+	ast::Pass<CodeGenerator> cgv( os,
 			Options( pretty, generateC, lineMarks, printExprTypes ) );
 	for ( auto & decl : translationUnit.decls ) {
Index: src/CodeGen/Generate.h
===================================================================
--- src/CodeGen/Generate.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/Generate.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -17,8 +17,4 @@
 
 #include <iostream>  // for ostream
-#include <list>      // for list
-
-class BaseSyntaxNode;
-class Declaration;
 
 namespace ast {
@@ -27,9 +23,4 @@
 
 namespace CodeGen {
-	/// Generates code. doIntrinsics determines if intrinsic functions are printed, pretty formats output nicely (e.g., uses unmangled names, etc.), generateC is true when the output must consist only of C code (allows some assertions, etc.)
-	void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC = false , bool lineMarks = false, bool printTypeExpr = false );
-
-	/// Generate code for a single node -- helpful for debugging in gdb
-	void generate( BaseSyntaxNode * node, std::ostream & os );
 
 /// Generates all code in transUnit and writing it to the os.
Index: src/CodeGen/LinkOnce.cc
===================================================================
--- src/CodeGen/LinkOnce.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/LinkOnce.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -22,50 +22,8 @@
 #include "AST/Expr.hpp"
 #include "AST/Pass.hpp"
-#include "Common/PassVisitor.h"       // for PassVisitor, WithShortCircuiting
 
 namespace CodeGen {
 
 namespace {
-
-bool is_cfa_linkonce_old( Attribute const * attr ) {
-	return std::string("cfa_linkonce") == attr->name;
-}
-
-bool is_section_attribute_old( Attribute const * attr ) {
-	return std::string("section") == attr->name;
-}
-
-class LinkOnceVisitorCore : public WithShortCircuiting {
-public:
-	void previsit( Declaration * ) {
-		visit_children = false;
-	}
-
-	void previsit( DeclarationWithType * decl ) {
-		std::list< Attribute * > & attributes = decl->attributes;
-		// See if we can find the element:
-		auto found = std::find_if(attributes.begin(), attributes.end(), is_cfa_linkonce_old );
-		if ( attributes.end() != found ) {
-			// Remove any other sections:
-			attributes.remove_if( is_section_attribute_old );
-			// Iterator to the cfa_linkonce attribute should still be valid.
-			Attribute * attribute = *found;
-			assert( attribute->parameters.empty() );
-			assert( !decl->mangleName.empty() );
-			// Overwrite the attribute in place.
-			const std::string section_name = ".gnu.linkonce." + decl->mangleName;
-			attribute->name = "section";
-			attribute->parameters.push_back(
-				new ConstantExpr( Constant::from_string( section_name ) )
-			);
-
-			// Unconditionnaly add "visibility(default)" to anything with gnu.linkonce
-			// visibility is a mess otherwise
-			attributes.push_back(new Attribute("visibility", {new ConstantExpr( Constant::from_string( "default" ) )}));
-
-		}
-		visit_children = false;
-	}
-};
 
 bool is_cfa_linkonce( ast::Attribute const * attr ) {
@@ -122,9 +80,4 @@
 } // namespace
 
-void translateLinkOnce( std::list< Declaration *> & translationUnit ) {
-	PassVisitor<LinkOnceVisitorCore> translator;
-	acceptAll( translationUnit, translator );
-}
-
 void translateLinkOnce( ast::TranslationUnit & translationUnit ) {
 	ast::Pass<LinkOnceCore>::run( translationUnit );
Index: src/CodeGen/LinkOnce.h
===================================================================
--- src/CodeGen/LinkOnce.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/LinkOnce.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -20,7 +20,5 @@
 // for now its almost the only attribute we handle.
 
-#include <list>  // for list
 
-class Declaration;
 namespace ast {
 	class TranslationUnit;
@@ -29,5 +27,4 @@
 namespace CodeGen {
 
-void translateLinkOnce( std::list< Declaration *> & translationUnit );
 void translateLinkOnce( ast::TranslationUnit & translationUnit );
 /* Convert the cfa_linkonce attribute on top level declaration into
Index: src/CodeGen/module.mk
===================================================================
--- src/CodeGen/module.mk	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/CodeGen/module.mk	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,21 +16,18 @@
 
 SRC_CODEGEN = \
-	CodeGen/FixMain2.cc \
-	CodeGen/FixMain.h \
+	CodeGen/CodeGeneratorNew.cpp \
+	CodeGen/CodeGeneratorNew.hpp \
+	CodeGen/GenType.cc \
+	CodeGen/GenType.h \
 	CodeGen/OperatorTable.cc \
 	CodeGen/OperatorTable.h
 
 SRC += $(SRC_CODEGEN) \
-	CodeGen/CodeGenerator.cc \
-	CodeGen/CodeGenerator.h \
-	CodeGen/CodeGeneratorNew.cpp \
-	CodeGen/CodeGeneratorNew.hpp \
 	CodeGen/Generate.cc \
 	CodeGen/Generate.h \
 	CodeGen/FixMain.cc \
+	CodeGen/FixMain.h \
 	CodeGen/FixNames.cc \
 	CodeGen/FixNames.h \
-	CodeGen/GenType.cc \
-	CodeGen/GenType.h \
 	CodeGen/LinkOnce.cc \
 	CodeGen/LinkOnce.h \
Index: c/CodeTools/DeclStats.cc
===================================================================
--- src/CodeTools/DeclStats.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,551 +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.
-//
-// DeclStats.cc --
-//
-// Author           : Aaron Moss
-// Created On       : Wed Jan 31 16:40:00 2016
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Dec 13 23:39:33 2019
-// Update Count     : 2
-//
-
-#include "DeclStats.h"
-
-#include <iostream>                // for operator<<, basic_ostream, cout
-#include <map>                     // for map
-#include <string>                  // for string, operator+, operator<<, cha...
-#include <unordered_map>           // for unordered_map
-#include <unordered_set>           // for unordered_set
-#include <utility>                 // for pair, make_pair
-
-#include "Common/PassVisitor.h"
-#include "Common/VectorMap.h"      // for VectorMap
-#include "SynTree/LinkageSpec.h"   // for ::NoOfSpecs, Spec
-#include "SynTree/Declaration.h"   // for FunctionDecl, TypeDecl, Declaration
-#include "SynTree/Expression.h"    // for UntypedExpr, Expression
-#include "SynTree/Statement.h"     // for CompoundStmt
-#include "SynTree/Type.h"          // for Type, FunctionType, PointerType
-#include "SynTree/Visitor.h"       // for maybeAccept, Visitor, acceptAll
-
-namespace CodeTools {
-
-	struct DeclStats : public WithShortCircuiting {
-		template<typename T>
-		static void sum(T& a, const T& b) { a += b; }
-
-		static void sum(VectorMap<unsigned>& a, const VectorMap<unsigned>& b) {
-			a.reserve( b.size() );
-			for ( unsigned i = 0; i < b.size(); ++i ) {
-				a[i] += b[i];
-			}
-		}
-
-		template<typename K>
-		static void sum(std::map<K, unsigned>& a, const std::map<K, unsigned>& b) {
-			for ( const auto& entry : b ) {
-				a[ entry.first ] += entry.second;
-			}
-		}
-
-		template<typename K>
-		static void sum(std::unordered_map<K, unsigned>& a, const std::unordered_map<K, unsigned>& b) {
-			for ( const auto& entry : b ) {
-				a[ entry.first ] += entry.second;
-			}
-		}
-
-		struct ArgPackStats {
-			VectorMap<unsigned> n;                   ///< Count of decls with each number of elements
-			VectorMap<unsigned> n_basic;             ///< Count of decls with each number of basic type elements
-			VectorMap<unsigned> n_generic;           ///< Count of decls with each number of generic type elements
-			VectorMap<unsigned> n_poly;              ///< Count of decls with each number of polymorphic elements
-			VectorMap<unsigned> n_compound;          ///< Count of decls with each number of non-generic compound types
-			std::map<unsigned, unsigned> p_basic;    ///< Count of decls with each percentage of basic type elements
-			std::map<unsigned, unsigned> p_generic;  ///< Count of decls with each percentage of generic type elements
-			std::map<unsigned, unsigned> p_poly;     ///< Count of decls with each percentage of polymorphic elements
-			std::map<unsigned, unsigned> p_compound; ///< Count of decls with each percentage of non-generic compound type elements
-			VectorMap<unsigned> n_types;             ///< Count of decls with each number of distinct types in the pack
-			/// Count of decls with each percentage of new types in lists.
-			/// Types used in the parameter list that recur in the return list are not considered to be new.
-			std::map<unsigned, unsigned> p_new;
-
-			ArgPackStats& operator+= (const ArgPackStats& o) {
-				sum(n, o.n);
-				sum(n_basic, o.n_basic);
-				sum(n_generic, o.n_generic);
-				sum(n_poly, o.n_poly);
-				sum(n_compound, o.n_compound);
-				sum(p_basic, o.p_basic);
-				sum(p_generic, o.p_generic);
-				sum(p_poly, o.p_poly);
-				sum(p_compound, o.p_compound);
-				sum(n_types, o.n_types);
-				sum(p_new, o.p_new);
-
-				return *this;
-			}
-		};
-
-		struct Stats {
-			unsigned n_decls;     ///< Total number of declarations
-			/// Count of declarations with each number of assertion parameters
-			VectorMap<unsigned> n_type_params;
-			/// Count of generic types with each number of type parameters
-			VectorMap<unsigned> n_generic_params;
-			/// Count of maximum nesting depth of types
-			VectorMap<unsigned> n_generic_nesting;
-			/// Count of declarations with each name
-			std::unordered_map<std::string, unsigned> by_name;
-			/// Count of uses of each basic type
-			std::unordered_map<std::string, unsigned> basic_type_names;
-			/// Count of uses of each generic type name (includes "*", "[]", "(*)", "[,]")
-			std::unordered_map<std::string, unsigned> generic_type_names;
-			/// Count of uses of each non-generic aggregate type
-			std::unordered_map<std::string, unsigned> compound_type_names;
-			/// Count of decls using each basic type
-			std::unordered_map<std::string, unsigned> basic_type_decls;
-			/// Count of decls using each generic type (includes "*", "[]", "(*)", "[,]")
-			std::unordered_map<std::string, unsigned> generic_type_decls;
-			/// Count of decls using each compound type
-			std::unordered_map<std::string, unsigned> compound_type_decls;
-			/// Stats for the parameter list
-			ArgPackStats params;
-			/// Stats for the return list
-			ArgPackStats returns;
-
-			/// Count of declarations with each number of assertions
-			std::map<unsigned, unsigned> n_assns;
-			/// Stats for the assertions' parameters
-			ArgPackStats assn_params;
-			/// Stats for the assertions' return types
-			ArgPackStats assn_returns;
-
-			Stats() : n_decls(0), n_type_params(), n_generic_params(), n_generic_nesting(),
-				by_name(), basic_type_names(), generic_type_names(), compound_type_names(),
-				basic_type_decls(), generic_type_decls(), compound_type_decls(), params(),
-				returns(), n_assns(), assn_params(), assn_returns() {}
-
-		public:
-			Stats& operator+= (const Stats& o) {
-				sum( n_decls, o.n_decls );
-				sum( n_type_params, o.n_type_params );
-				sum( n_generic_params, o.n_generic_params );
-				sum( n_generic_nesting, o.n_generic_nesting );
-				sum( by_name, o.by_name );
-				sum( basic_type_names, o.basic_type_names );
-				sum( generic_type_names, o.generic_type_names );
-				sum( compound_type_names, o.compound_type_names );
-				sum( basic_type_decls, o.basic_type_decls );
-				sum( generic_type_decls, o.generic_type_decls );
-				sum( compound_type_decls, o.compound_type_decls );
-				sum( params, o.params );
-				sum( returns, o.returns );
-				sum( n_assns, o.n_assns );
-				sum( assn_params, o.assn_params );
-				sum( assn_returns, o.assn_returns );
-
-				return *this;
-			}
-		};
-
-		/// number of counting bins for linkages
-		static const unsigned n_named_specs = 8;
-		/// Mapping function from linkage to bin.
-		static unsigned linkage_index( LinkageSpec::Spec spec ) {
-			switch ( spec ) {
-			case LinkageSpec::Intrinsic:  return 0;
-			case LinkageSpec::C:          return 1;
-			case LinkageSpec::Cforall:    return 2;
-			case LinkageSpec::AutoGen:    return 3;
-			case LinkageSpec::Compiler:   return 4;
-			case LinkageSpec::BuiltinCFA: return 5;
-			case LinkageSpec::BuiltinC:   return 6;
-			default:                      return 7;
-			}
-		}
-
-		Stats for_linkage[n_named_specs];            ///< Stores separate stats per linkage
-		std::unordered_set<std::string> seen_names;  ///< Stores manglenames already seen to avoid double-counting
-		Stats total;
-		/// Count of expressions with (depth, fanout)
-		std::map<std::pair<unsigned, unsigned>, unsigned> exprs_by_fanout_at_depth;
-
-		void countType( const std::string& name, unsigned& n, std::unordered_map<std::string,
-				unsigned>& names, std::unordered_map<std::string, unsigned>& decls,
-				std::unordered_set<std::string>& elSeen ) {
-			++n;
-			++names[ name ];
-			if ( elSeen.insert( name ).second ) { ++decls[ name ]; }
-		}
-
-		void update_max( unsigned& max, unsigned crnt ) {
-			if ( crnt > max ) max = crnt;
-		}
-
-		void analyzeSubtype( Type* ty, Stats& stats, std::unordered_set<std::string>& elSeen,
-				unsigned& n_poly, bool& seen_poly, unsigned& max_depth, unsigned depth ) {
-			unsigned x;
-			analyzeType( ty, stats, elSeen, x, x, n_poly, x, seen_poly, max_depth, depth + 1 );
-		}
-
-		void analyzeSubtypes( std::list<DeclarationWithType*>& tys, Stats& stats,
-				std::unordered_set<std::string>& elSeen, unsigned& n_poly, bool& seen_poly,
-				unsigned& max_depth, unsigned depth, unsigned& n_subs ) {
-			for ( DeclarationWithType* dwt : tys ) {
-				Type* ty = dwt->get_type();
-				n_subs += (unsigned)( dynamic_cast<VoidType*>(ty) != nullptr );
-				analyzeSubtype( ty, stats, elSeen, n_poly, seen_poly, max_depth, depth );
-			}
-		}
-
-		void analyzeSubtypes( std::list<Expression*>& tys, Stats& stats,
-				std::unordered_set<std::string>& elSeen, unsigned& n_poly, bool& seen_poly,
-				unsigned& max_depth, unsigned depth ) {
-			for ( Expression* expr : tys ) {
-				TypeExpr* texpr = dynamic_cast<TypeExpr*>(expr);
-				if ( ! texpr ) continue;
-				Type* ty = texpr->get_type();
-				analyzeSubtype( ty, stats, elSeen, n_poly, seen_poly, max_depth, depth );
-			}
-		}
-
-		void analyzeSubtypes( std::list<Type*>& tys, Stats& stats,
-				std::unordered_set<std::string>& elSeen, unsigned& n_poly, bool& seen_poly,
-				unsigned& max_depth, unsigned depth ) {
-			for ( Type* ty : tys ) {
-				analyzeSubtype( ty, stats, elSeen, n_poly, seen_poly, max_depth, depth );
-			}
-		}
-
-		void analyzeType( Type* ty, Stats& stats, std::unordered_set<std::string>& elSeen,
-				unsigned& n_basic, unsigned& n_generic, unsigned& n_poly, unsigned& n_agg,
-				bool& seen_poly, unsigned& max_depth, unsigned depth = 0 ) {
-			if ( BasicType* bt = dynamic_cast<BasicType*>(ty) ) {
-				std::string name = BasicType::typeNames[ bt->get_kind() ];
-				countType( name, n_basic, stats.basic_type_names, stats.basic_type_decls, elSeen );
-				update_max( max_depth, depth );
-			} else if ( PointerType* pt = dynamic_cast<PointerType*>(ty) ) {
-				std::string name = "*";
-				countType(
-					name, n_generic, stats.generic_type_names, stats.generic_type_decls, elSeen);
-				analyzeSubtype(
-					pt->get_base(), stats, elSeen, n_poly, seen_poly, max_depth, depth );
-				++stats.n_generic_params.at( 1 );
-			} else if ( ArrayType* at = dynamic_cast<ArrayType*>(ty) ) {
-				std::string name = "[]";
-				countType(
-					name, n_generic, stats.generic_type_names, stats.generic_type_decls, elSeen);
-				analyzeSubtype(
-					at->get_base(), stats, elSeen, n_poly, seen_poly, max_depth, depth );
-				++stats.n_generic_params.at( 1 );
-			} else if ( ReferenceType* rt = dynamic_cast<ReferenceType*>(ty) ) {
-				std::string name = "&";
-				countType(
-					name, n_generic, stats.generic_type_names, stats.generic_type_decls, elSeen);
-				analyzeSubtype(
-					rt->get_base(), stats, elSeen, n_poly, seen_poly, max_depth, depth );
-				++stats.n_generic_params.at( 1 );
-			} else if ( FunctionType* ft = dynamic_cast<FunctionType*>(ty) ) {
-				std::string name = "(*)";
-				countType(
-					name, n_generic, stats.generic_type_names, stats.generic_type_decls, elSeen);
-				unsigned n_subs = 0;
-				analyzeSubtypes(
-					ft->get_returnVals(), stats, elSeen, n_poly, seen_poly, max_depth, depth,
-					n_subs );
-				analyzeSubtypes(
-					ft->get_parameters(), stats, elSeen, n_poly, seen_poly, max_depth, depth,
-					n_subs );
-				++stats.n_generic_params.at( n_subs );
-			} else if ( TypeInstType* vt = dynamic_cast<TypeInstType*>(ty) ) {
-				if ( ! seen_poly ) {
-					++n_poly;
-					seen_poly = true;
-				}
-				countType(
-					vt->get_name(), n_agg, stats.compound_type_names, stats.compound_type_decls,
-					elSeen );
-				update_max( max_depth, depth );
-			} else if ( ReferenceToType* st = dynamic_cast<ReferenceToType*>(ty) ) {
-				std::list<Expression*>& params = st->get_parameters();
-				if ( params.empty() ) {
-					countType(
-						st->get_name(), n_agg, stats.compound_type_names,
-						stats.compound_type_decls, elSeen );
-					update_max( max_depth, depth );
-				} else {
-					countType(
-						st->get_name(), n_generic, stats.generic_type_names,
-						stats.generic_type_decls, elSeen);
-					analyzeSubtypes( params, stats, elSeen, n_poly, seen_poly, max_depth, depth );
-					++stats.n_generic_params.at( params.size() );
-				}
-			} else if ( TupleType* tt = dynamic_cast<TupleType*>(ty) ) {
-				std::string name = "[,]";
-				countType(
-					name, n_generic, stats.generic_type_names, stats.generic_type_decls, elSeen);
-				analyzeSubtypes(
-					tt->get_types(), stats, elSeen, n_poly, seen_poly, max_depth, depth );
-				++stats.n_generic_params.at( tt->size() );
-			} else if ( dynamic_cast<VarArgsType*>(ty) ) {
-				std::string name = "...";
-				countType(
-					name, n_agg, stats.compound_type_names, stats.compound_type_decls, elSeen );
-				update_max( max_depth, depth );
-			} else if ( dynamic_cast<ZeroType*>(ty) ) {
-				std::string name = "0";
-				countType( name, n_basic, stats.basic_type_names, stats.basic_type_decls, elSeen );
-				update_max( max_depth, depth );
-			} else if ( dynamic_cast<OneType*>(ty) ) {
-				std::string name = "1";
-				countType( name, n_basic, stats.basic_type_names, stats.basic_type_decls, elSeen );
-				update_max( max_depth, depth );
-			}
-		}
-
-		/// Update arg pack stats based on a declaration list
-		void analyze( Stats& stats, std::unordered_set<std::string>& seen,
-				std::unordered_set<std::string>& elSeen, ArgPackStats& pstats,
-				std::list<DeclarationWithType*>& decls ) {
-			std::unordered_set<std::string> types;
-			unsigned n = 0;                 ///< number of args/returns
-			unsigned n_basic = 0;           ///< number of basic types
-			unsigned n_generic = 0;         ///< number of generic types (includes "*", "&", "[]", "(*)", "[,]")
-			unsigned n_poly = 0;            ///< number of polymorphic types
-			unsigned n_agg = 0;             ///< number of non-generic aggregate types
-			unsigned n_new = 0;             ///< number of new types
-
-			for ( auto decl : decls ) {
-				Type* dt = decl->get_type();
-
-				n += dt->size();
-
-				std::stringstream ss;
-				dt->print( ss );
-				types.insert( ss.str() );
-				if ( seen.insert( ss.str() ).second ) { ++n_new; }
-
-				bool seen_poly = false;
-				unsigned max_depth = 0;
-				analyzeType(
-					dt, stats, elSeen, n_basic, n_generic, n_poly, n_agg, seen_poly, max_depth );
-				++stats.n_generic_nesting.at( max_depth );
-			}
-
-			++pstats.n.at( n );
-			++pstats.n_basic.at( n_basic );
-			++pstats.n_generic.at( n_generic );
-			++pstats.n_poly.at( n_poly );
-			++pstats.n_compound.at( n_agg );
-			if ( n > 0 ) {
-				++pstats.p_basic[ n_basic*100/n ];
-				++pstats.p_generic[ n_generic*100/n ];
-				++pstats.p_poly[ n_poly*100/n ];
-				++pstats.p_compound[ n_agg*100/n ];
-				if ( n > 1 ) ++pstats.p_new[ (n_new-1)*100/(n-1) ];
-			}
-			++pstats.n_types.at( types.size() );
-		}
-
-		void analyzeFunc( FunctionType* fnTy, Stats& stats, ArgPackStats& params, ArgPackStats& returns ) {
-			std::unordered_set<std::string> seen;
-			std::unordered_set<std::string> elSeen;
-			analyze( stats, seen, elSeen, params, fnTy->get_parameters() );
-			analyze( stats, seen, elSeen, returns, fnTy->get_returnVals() );
-		}
-
-		void analyzeExpr( UntypedExpr *expr, unsigned depth ) {
-			auto& args = expr->get_args();
-			unsigned fanout = args.size();
-
-			++exprs_by_fanout_at_depth[ std::make_pair(depth, fanout) ];
-			for ( Expression* arg : args ) {
-				if ( UntypedExpr *uearg = dynamic_cast<UntypedExpr*>(arg) ) {
-					analyzeExpr( uearg, depth+1 );
-				}
-			}
-		}
-
-	public:
-		void previsit( FunctionDecl *decl ) {
-			// skip if already seen declaration for this function
-			const std::string& mangleName = decl->get_mangleName().empty() ? decl->name : decl->get_mangleName();
-			if ( seen_names.insert( mangleName ).second ) {
-				Stats& stats = for_linkage[ linkage_index( decl->linkage ) ];
-
-				++stats.n_decls;
-				FunctionType* fnTy = decl->type;
-				const Type::ForallList& forall = fnTy->forall;
-				++stats.n_type_params.at( forall.size() );
-				unsigned n_assns = 0;
-				for ( TypeDecl* fdecl : forall ) {
-					n_assns += fdecl->assertions.size();
-					for ( DeclarationWithType* assn : fdecl->assertions ) {
-						FunctionType *assnTy = nullptr;
-						if ( ObjectDecl *assnObj = dynamic_cast<ObjectDecl*>(assn) ) {
-							if ( PointerType *ptrTy = dynamic_cast<PointerType*>(assnObj->get_type()) ) {
-								assnTy = dynamic_cast<FunctionType*>(ptrTy->base);
-							} else assnTy = dynamic_cast<FunctionType*>(assnObj->get_type());
-						} else if ( FunctionDecl *assnDecl = dynamic_cast<FunctionDecl*>(assn) ) {
-							assnTy = assnDecl->type;
-						}
-						if ( assnTy ) analyzeFunc( assnTy, stats, stats.assn_params, stats.assn_returns );
-					}
-				}
-				++stats.n_assns[ n_assns ];
-				++stats.by_name[ decl->name ];
-				analyzeFunc( fnTy, stats, stats.params, stats.returns );
-			}
-		}
-
-		void previsit( UntypedExpr *expr ) {
-			visit_children = false;
-			analyzeExpr( expr, 0 );
-		}
-
-	private:
-		template<typename F>
-		void printAll( const std::string& name, F extract ) {
-			std::cout << "\"" << name << "\",";
-			for ( const auto& stats : for_linkage ) {
-				std::cout << "," << extract(stats);
-			}
-			std::cout << "," << extract(total) << std::endl;
-		}
-
-		template<typename F>
-		void printAllMap( const std::string& name, F extract ) {
-			for ( const auto& entry : extract(total) ) {
-				const auto& key = entry.first;
-				std::cout << "\"" << name << "\"," << key;
-				for ( const auto& stats : for_linkage ) {
-					const auto& map = extract(stats);
-					auto it = map.find( key );
-					if ( it == map.end() ) std::cout << ",0";
-					else std::cout << "," << it->second;
-				}
-				std::cout  << "," << entry.second << std::endl;
-			}
-		}
-
-		template<typename F>
-		void printAllHisto( const std::string& name, F extract ) {
-			VectorMap<unsigned> histos[n_named_specs];
-			VectorMap<unsigned> thisto;
-
-			for ( const auto& entry : extract(total) ) { ++thisto.at( entry.second ); }
-
-			for ( unsigned i = 0; i < n_named_specs; ++i ) {
-				// can't be a higher count in one of the sub-histograms than the total
-				histos[i].reserve( thisto.size() );
-
-				for ( const auto& entry : extract(for_linkage[i]) ) { ++histos[i][entry.second]; }
-			}
-
-			for ( unsigned i = 0; i < thisto.size(); ++i ) {
-				std::cout << "\"" << name << "\"," << i;
-				for ( const auto& histo : histos ) {
-					std::cout << "," << histo[i];
-				}
-				std::cout << "," << thisto[i] << std::endl;
-			}
-		}
-
-		template<typename F>
-		void printAllSparseHisto( const std::string& name, F extract ) {
-			std::map<unsigned, unsigned> histos[n_named_specs];
-			std::map<unsigned, unsigned> thisto;
-
-			for ( const auto& entry : extract(total) ) { ++thisto[ entry.second ]; }
-
-			for ( unsigned i = 0; i < n_named_specs; ++i ) {
-				for ( const auto& entry : extract(for_linkage[i]) ) { ++histos[i][entry.second]; }
-			}
-
-			for ( const auto& entry : thisto ) {
-				const auto& key = entry.first;
-				std::cout << "\"" << name << "\"," << key;
-				for ( unsigned i = 0; i < n_named_specs; ++i ) {
-					auto it = histos[i].find( key );
-					if ( it == histos[i].end() ) std::cout << ",0";
-					else std::cout << "," << it->second;
-				}
-				std::cout << "," << entry.second << std::endl;
-			}
-		}
-
-		template<typename F>
-		void printAllPack( const std::string& name, F extract ) {
-			printAllMap("n_basic_" + name, [&extract](const Stats& stats) { return extract(stats).n_basic; });
-			printAllMap("n_generic_" + name, [&extract](const Stats& stats) { return extract(stats).n_generic; });
-			printAllMap("n_poly_" + name, [&extract](const Stats& stats) { return extract(stats).n_poly; });
-			printAllMap("n_compound_" + name, [&extract](const Stats& stats) { return extract(stats).n_compound; });
-			printAllMap("n_" + name, [&extract](const Stats& stats) { return extract(stats).n; });
-			printAllMap("%_basic_" + name, [&extract](const Stats& stats) { return extract(stats).p_basic; });
-			printAllMap("%_generic_" + name, [&extract](const Stats& stats) { return extract(stats).p_generic; });
-			printAllMap("%_poly_" + name, [&extract](const Stats& stats) { return extract(stats).p_poly; });
-			printAllMap("%_compound_" + name, [&extract](const Stats& stats) { return extract(stats).p_compound; });
-			printAllMap("n_distinct_types_" + name, [&extract](const Stats& stats) { return extract(stats).n_types; });
-			printAllMap("%_new_types_in_" + name, [&extract](const Stats& stats) { return extract(stats).p_new; });
-		}
-
-		void printPairMap( const std::string& name,
-		                   const std::map<std::pair<unsigned, unsigned>, unsigned>& map ) {
-			for ( const auto& entry : map ) {
-				const auto& key = entry.first;
-				std::cout << "\"" << name << "\"," << key.first << "," << key.second << ","
-				          << entry.second << std::endl;
-			}
-		}
-
-	public:
-		void print() {
-			for ( auto& stats : for_linkage ) {
-				total += stats;
-			}
-
-			std::cout << ",,\"intrinsic\",\"Cforall\",\"C\",\"autogen\",\"compiler\",\"builtinCFA\",\"builtinC\",\"other\",\"TOTAL\"" << std::endl;
-
-			printAllMap("n_type_params", [](const Stats& stats) { return stats.n_type_params; });
-			printAllMap("n_generic_params", [](const Stats& stats) { return stats.n_generic_params; });
-			printAllMap("n_generic_nesting", [](const Stats& stats) { return stats.n_generic_nesting; });
-			printAll("n_decls", [](const Stats& stats) { return stats.n_decls; });
-			printAll("unique_names", [](const Stats& stats) { return stats.by_name.size(); });
-			printAllSparseHisto("overloads", [](const Stats& stats) { return stats.by_name; });
-			printAll("basic_type_names", [](const Stats& stats) { return stats.basic_type_names.size(); });
-			printAllSparseHisto("basic_type_uses", [](const Stats& stats) { return stats.basic_type_names; });
-			printAllSparseHisto("decls_using_basic_type", [](const Stats& stats) { return stats.basic_type_decls; });
-			printAll("generic_type_names", [](const Stats& stats) { return stats.generic_type_names.size(); });
-			printAllSparseHisto("generic_type_uses", [](const Stats& stats) { return stats.generic_type_names; });
-			printAllSparseHisto("decls_using_generic_type", [](const Stats& stats) { return stats.generic_type_decls; });
-			printAll("compound_type_names", [](const Stats& stats) { return stats.compound_type_names.size(); });
-			printAllSparseHisto("compound_type_uses", [](const Stats& stats) { return stats.compound_type_names; });
-			printAllSparseHisto("decls_using_compound_type", [](const Stats& stats) { return stats.compound_type_decls; });
-			printAllPack("params", [](const Stats& stats) { return stats.params; });
-			printAllPack("returns", [](const Stats& stats) { return stats.returns; });
-			printAllMap("n_assns", [](const Stats& stats) { return stats.n_assns; });
-			printAllPack("assn_params", [](const Stats& stats) { return stats.assn_params; });
-			printAllPack("assn_returns", [](const Stats& stats) { return stats.assn_returns; });
-			std::cout << std::endl;
-
-			printPairMap("exprs_by_depth+fanout", exprs_by_fanout_at_depth);
-		}
-	};
-
-	void printDeclStats( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<DeclStats> stats;
-		acceptAll( translationUnit, stats );
-		stats.pass.print();
-	}
-
-} // namespace CodeTools
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/CodeTools/DeclStats.h
===================================================================
--- src/CodeTools/DeclStats.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,33 +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.
-//
-// DeclStats.h -- Prints summary information about a translation unit's declarations.
-//
-// Author           : Aaron Moss
-// Created On       : Wed Jan 31 16:40:00 2016
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul 21 22:17:56 2017
-// Update Count     : 2
-//
-
-#pragma once
-
-#include <list>  // for list
-
-class Declaration;
-
-namespace CodeTools {
-
-	/// Prints summary information about a translation unit's function declarations and calls
-	void printDeclStats( std::list< Declaration * > &translationUnit );
-	
-}  // namespace CodeTools
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/CodeTools/ResolvProtoDump.cc
===================================================================
--- src/CodeTools/ResolvProtoDump.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,771 +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.
-//
-// ResolvProtoDump.cc -- Translates CFA resolver instances into resolv-proto instances
-//
-// Author           : Aaron Moss
-// Created On       : Tue Sep 11 09:04:00 2018
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Feb 15 13:50:11 2020
-// Update Count     : 3
-//
-
-#include <algorithm>
-#include <cctype>
-#include <iostream>
-#include <memory>
-#include <list>
-#include <set>
-#include <sstream>
-#include <string>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-#include "Common/PassVisitor.h"
-#include "Common/utility.h"
-#include "CodeGen/OperatorTable.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/Expression.h"
-#include "SynTree/Initializer.h"
-#include "SynTree/Statement.h"
-#include "SynTree/Type.h"
-
-namespace CodeTools {
-
-	/// Visitor for dumping resolver prototype output
-	class ProtoDump : public WithShortCircuiting, public WithVisitorRef<ProtoDump> {
-		std::set<std::string> decls;             ///< Declarations in this scope
-		std::vector<std::string> exprs;          ///< Expressions in this scope
-		std::vector<ProtoDump> subs;             ///< Sub-scopes
-		std::unordered_set<std::string> closed;  ///< Closed type variables
-		const ProtoDump* parent;                 ///< Outer lexical scope
-		std::unique_ptr<Type> rtnType;           ///< Return type for this scope
-
-	public:
-		/// Default constructor for root ProtoDump
-		ProtoDump() : decls(), exprs(), subs(), closed(), parent(nullptr), rtnType(nullptr) {}
-
-		/// Child constructor
-		ProtoDump(const ProtoDump* p, Type* r)
-			: decls(), exprs(), subs(), closed(p->closed), parent(p), rtnType(r) {}
-
-		// Fix copy issues
-		ProtoDump(const ProtoDump& o)
-			: decls(o.decls), exprs(o.exprs), subs(o.subs), closed(o.closed), parent(o.parent),
-			  rtnType(maybeClone(o.rtnType.get())) {}
-		ProtoDump( ProtoDump&& ) = default;
-
-		ProtoDump& operator= (const ProtoDump& o) {
-			if ( this == &o ) return *this;
-
-			decls = o.decls;
-			exprs = o.exprs;
-			subs = o.subs;
-			closed = o.closed;
-			parent = o.parent;
-			rtnType.reset( maybeClone(o.rtnType.get()) );
-
-			return *this;
-		}
-		ProtoDump& operator= (ProtoDump&&) = delete;
-
-	private:
-		/// checks if this declaration is contained in the scope or one of its parents
-		bool hasDecl( const std::string& s ) const {
-			if ( decls.count( s ) ) return true;
-			if ( parent ) return parent->hasDecl( s );
-			return false;
-		}
-
-		/// adds a new declaration to this scope, providing it does not already exist
-		void addDecl( const std::string& s ) {
-			if ( ! hasDecl( s ) ) decls.insert( s );
-		}
-
-		/// adds a new expression to this scope
-		void addExpr( const std::string& s ) {
-			if ( ! s.empty() ) { exprs.emplace_back( s ); }
-		}
-
-		/// adds a new subscope to this scope, returning a reference
-		void addSub( PassVisitor<ProtoDump>&& sub ) {
-			subs.emplace_back( std::move(sub.pass) );
-		}
-
-		/// Whether lists should be separated, terminated, or preceded by their separator
-		enum septype { separated, terminated, preceded };
-
-		/// builds space-separated list of types
-		template<typename V>
-		static void build( V& visitor, const std::list< Type* >& tys, std::stringstream& ss,
-				septype mode = separated ) {
-			if ( tys.empty() ) return;
-
-			if ( mode == preceded ) { ss << ' '; }
-
-			auto it = tys.begin();
-			(*it)->accept( visitor );
-
-			while ( ++it != tys.end() ) {
-				ss << ' ';
-				(*it)->accept( visitor );
-			}
-
-			if ( mode == terminated ) { ss << ' '; }
-		}
-
-		/// builds list of types wrapped as tuple type
-		template<typename V>
-		static void buildAsTuple( V& visitor, const std::list< Type* >& tys,
-				std::stringstream& ss ) {
-			switch ( tys.size() ) {
-				case 0: ss << "#void"; break;
-				case 1: tys.front()->accept( visitor ); break;
-				default:
-					ss << "#$" << tys.size() << '<';
-					build( visitor, tys, ss );
-					ss << '>';
-					break;
-			}
-		}
-
-		/// gets types from DWT list
-		static std::list< Type* > from_decls( const std::list< DeclarationWithType* >& decls ) {
-			std::list< Type* > tys;
-			for ( auto decl : decls ) { tys.emplace_back( decl->get_type() ); }
-			return tys;
-		}
-
-		/// gets types from TypeExpr list
-		static std::list< Type* > from_exprs( const std::list< Expression* >& exprs ) {
-			std::list< Type* > tys;
-			for ( auto expr : exprs ) {
-				if ( TypeExpr* tyExpr = dynamic_cast<TypeExpr*>(expr) ) {
-					tys.emplace_back( tyExpr->type );
-				}
-			}
-			return tys;
-		}
-
-		/// builds prefixes for rp_name
-		static std::string new_prefix( const std::string& old, const char* added ) {
-			if ( old.empty() ) return std::string{"$"} + added;
-			return old + added;
-		}
-
-		/// shortens operator names
-		static void op_name( const std::string& name, std::stringstream& ss ) {
-			if ( name.compare( 0, 10, "_operator_" ) == 0 ) {
-				ss << name.substr(10);
-			} else if ( name.compare( "_constructor" ) == 0
-					|| name.compare( "_destructor" ) == 0 ) {
-				ss << name.substr(1);
-			} else if ( name.compare( 0, 11, "__operator_" ) == 0 ) {
-				ss << name.substr(11);
-			} else {
-				ss << name;
-			}
-		}
-
-		/// replaces operators with resolv-proto names
-		static void rp_name( const std::string& name, std::stringstream& ss,
-				std::string&& pre = "" ) {
-			// safety check for anonymous names
-			if ( name.empty() ) {
-				ss << new_prefix(pre, "anon");
-				return;
-			}
-
-			// replace operator names
-			const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( name );
-			if ( opInfo ) {
-				ss << new_prefix(pre, "");
-				op_name( opInfo->outputName, ss );
-				return;
-			}
-
-			// replace retval names
-			if ( name.compare( 0, 8, "_retval_" ) == 0 ) {
-				ss << new_prefix(pre, "rtn_");
-				op_name( name.substr(8), ss );
-				return;
-			}
-
-			// default to just name, with first character in lowercase
-			ss << pre
-			   << (char)std::tolower( static_cast<unsigned char>(name[0]) )
-			   << (name.c_str() + 1);
-		}
-
-		/// ensures type inst names are uppercase
-		static void ti_name( const std::string& name, std::stringstream& ss ) {
-			// replace built-in wide character types with named types
-			if ( name == "char16_t" || name == "char32_t" || name == "wchar_t" ) {
-				ss << "#" << name;
-				return;
-			}
-
-			// strip leading underscore
-			unsigned i = 0;
-			while ( i < name.size() && name[i] == '_' ) { ++i; }
-			if ( i == name.size() ) {
-				ss << "Anon";
-				return;
-			}
-
-			std::string stripped = name.substr(i);
-			// strip trailing "_generic_" from autogen names (avoids some user-generation issues)
-			char generic[] = "_generic_"; size_t n_generic = sizeof(generic) - 1;
-			if ( stripped.size() >= n_generic
-					&& stripped.substr( stripped.size() - n_generic ) == generic ) {
-				stripped.resize( stripped.size() - n_generic );
-			}
-
-			// uppercase first character
-			ss << (char)std::toupper( static_cast<unsigned char>(stripped[0]) )
-			   << (stripped.c_str() + 1);
-		}
-
-		/// Visitor for printing types
-		struct TypePrinter : public WithShortCircuiting, WithVisitorRef<TypePrinter>, WithGuards {
-			std::stringstream& ss;                          ///< Output to print to
-			const std::unordered_set<std::string>& closed;  ///< Closed type variables
-			unsigned depth;                                 ///< Depth of nesting from root type
-
-			TypePrinter( const std::unordered_set<std::string>& closed, std::stringstream& ss )
-				: ss(ss), closed(closed), depth(0) {}
-
-			// basic type represented as integer type
-			// TODO maybe hard-code conversion graph and make named type
-			void previsit( BasicType* bt ) { ss << (int)bt->get_kind(); }
-
-			// pointers (except function pointers) represented as generic type
-			void previsit( PointerType* pt ) {
-				if ( ! dynamic_cast<FunctionType*>(pt->base) ) { ss << "#$ptr<"; ++depth; }
-			}
-			void postvisit( PointerType* pt ) {
-				if ( ! dynamic_cast<FunctionType*>(pt->base) ) { --depth; ss << '>'; }
-			}
-
-			// arrays represented as generic pointers
-			void previsit( ArrayType* at ) {
-				ss << "#$ptr<";
-				++depth;
-				at->base->accept( *visitor );
-				--depth;
-				ss << '>';
-				visit_children = false;
-			}
-
-			// ignore top-level reference types, they're mostly transparent to resolution
-			void previsit( ReferenceType* ) {
-				if ( depth > 0 ) { ss << "#$ref<"; }
-				++depth;
-			}
-			void postvisit( ReferenceType* ) {
-				--depth;
-				if ( depth > 0 ) { ss << '>'; }
-			}
-
-			// print function types using prototype syntax
-			void previsit( FunctionType* ft ) {
-				ss << '[';
-				++depth;
-				build( *visitor, from_decls( ft->returnVals ), ss, preceded );
-				ss << " : ";
-				build( *visitor, from_decls( ft->parameters ), ss, terminated );
-				--depth;
-				ss << ']';
-				visit_children = false;
-			}
-
-		private:
-			// prints aggregate type name as NamedType with optional paramters
-			void handleAggregate( ReferenceToType* at ) {
-				ss << '#' << at->name;
-				if ( ! at->parameters.empty() ) {
-					ss << '<';
-					++depth;
-					build( *visitor, from_exprs( at->parameters ), ss );
-					--depth;
-					ss << '>';
-				}
-				visit_children = false;
-			}
-
-		public:
-			// handle aggregate types using NamedType
-			void previsit( StructInstType* st ) { handleAggregate( st ); }
-			void previsit( UnionInstType* ut ) { handleAggregate( ut ); }
-
-			// replace enums with int
-			void previsit( EnumInstType* ) { 
-				// TODO: add the meaningful representation of typed int
-				ss << (int)BasicType::SignedInt; 
-			}
-
-			void previsit( TypeInstType* vt ) {
-				// print closed variables as named types
-				if ( closed.count( vt->name ) ) { ss << '#' << vt->name; }
-				// otherwise make sure first letter is capitalized
-				else { ti_name( vt->name, ss ); }
-			}
-
-			// flattens empty and singleton tuples
-			void previsit( TupleType* tt ) {
-				++depth;
-				buildAsTuple( *visitor, tt->types, ss );
-				--depth;
-				visit_children = false;
-			}
-
-			// TODO support variable args for functions
-			void previsit( VarArgsType* ) {
-				// only include varargs for top level (argument type)
-				if ( depth == 0 ) { ss << "#$varargs"; }
-			}
-
-			// replace 0 and 1 with int
-			// TODO support 0 and 1 with their proper type names and conversions
-			void previsit( ZeroType* ) { ss << (int)BasicType::SignedInt; }
-			void previsit( OneType* ) { ss << (int)BasicType::SignedInt; }
-
-			// only print void type if not at top level
-			void previsit( VoidType* ) {
-				if ( depth > 0 ) { ss << "#void"; }
-			}
-		};
-
-		/// builds description of function
-		void build( const std::string& name, FunctionType* fnTy, std::stringstream& ss ) {
-			PassVisitor<TypePrinter> printTy{ closed, ss };
-			// print return values
-			build( printTy, from_decls( fnTy->returnVals ), ss, terminated );
-			// print name
-			rp_name( name, ss );
-			// print parameters
-			build( printTy, from_decls( fnTy->parameters ), ss, preceded );
-			// print assertions
-			for ( TypeDecl* tyvar : fnTy->forall ) {
-				for ( DeclarationWithType* assn : tyvar->assertions ) {
-					ss << " | ";
-					build( assn->name, assn->get_type(), ss );
-				}
-			}
-		}
-
-		/// builds description of a variable (falls back to function if function type)
-		void build( const std::string& name, Type* ty, std::stringstream& ss ) {
-			// ignore top-level references
-			Type *norefs = ty->stripReferences();
-
-			// fall back to function declaration if function type
-			if ( PointerType* pTy = dynamic_cast< PointerType* >(norefs) ) {
-				if ( FunctionType* fnTy = dynamic_cast< FunctionType* >(pTy->base) ) {
-					build( name, fnTy, ss );
-					return;
-				}
-			} else if ( FunctionType* fnTy = dynamic_cast< FunctionType* >(norefs) ) {
-				build( name, fnTy, ss );
-				return;
-			}
-
-			// print variable declaration in prototype syntax
-			PassVisitor<TypePrinter> printTy{ closed, ss };
-			norefs->accept( printTy );
-			ss << " &";
-			rp_name( name, ss );
-		}
-
-		/// builds description of a field access
-		void build( const std::string& name, AggregateDecl* agg, Type* ty, std::stringstream& ss ) {
-			// ignore top-level references
-			Type *norefs = ty->stripReferences();
-
-			// print access as new field name
-			PassVisitor<TypePrinter> printTy{ closed, ss };
-			norefs->accept( printTy );
-			ss << ' ';
-			rp_name( name, ss, "$field_" );
-			ss << " #" << agg->name;
-			// handle type parameters
-			if ( ! agg->parameters.empty() ) {
-				ss << '<';
-				auto it = agg->parameters.begin();
-				while (true) {
-					ti_name( (*it)->name, ss );
-					if ( ++it == agg->parameters.end() ) break;
-					ss << ' ';
-				}
-				ss << '>';
-			}
-		}
-
-		/// Visitor for printing expressions
-		struct ExprPrinter : WithShortCircuiting, WithVisitorRef<ExprPrinter> {
-			// TODO change interface to generate multiple expression candidates
-			const std::unordered_set<std::string>& closed;  ///< set of closed type vars
-			std::stringstream& ss;                          ///< Output to print to
-
-			ExprPrinter( const std::unordered_set<std::string>& closed, std::stringstream& ss )
-				: closed(closed), ss(ss) {}
-
-			/// Names handled as name expressions
-			void previsit( NameExpr* expr ) {
-				ss << '&';
-				rp_name( expr->name, ss );
-			}
-
-			/// Handle already-resolved variables as type constants
-			void previsit( VariableExpr* expr ) {
-				PassVisitor<TypePrinter> tyPrinter{ closed, ss };
-				expr->var->get_type()->accept( tyPrinter );
-				visit_children = false;
-			}
-
-			/// Calls handled as calls
-			void previsit( UntypedExpr* expr ) {
-				// TODO handle name extraction more generally
-				NameExpr* name = dynamic_cast<NameExpr*>(expr->function);
-
-				// fall back on just resolving call to function name
-				// TODO incorporate function type into resolv-proto
-				if ( ! name ) {
-					expr->function->accept( *visitor );
-					visit_children = false;
-					return;
-				}
-
-				rp_name( name->name, ss );
-				if ( expr->args.empty() ) {
-					ss << "()";
-				} else {
-					ss << "( ";
-					auto it = expr->args.begin();
-					while (true) {
-						(*it)->accept( *visitor );
-						if ( ++it == expr->args.end() ) break;
-						ss << ' ';
-					}
-					ss << " )";
-				}
-				visit_children = false;
-			}
-
-			/// Already-resolved calls reduced to their type constant
-			void previsit( ApplicationExpr* expr ) {
-				PassVisitor<TypePrinter> tyPrinter{ closed, ss };
-				expr->result->accept( tyPrinter );
-				visit_children = false;
-			}
-
-			/// Address-of handled as operator
-			void previsit( AddressExpr* expr ) {
-				ss << "$addr( ";
-				expr->arg->accept( *visitor );
-				ss << " )";
-				visit_children = false;
-			}
-
-			/// Casts replaced with result type
-			/// TODO put cast target functions in, and add second expression for target
-			void previsit( CastExpr* cast ) {
-				PassVisitor<TypePrinter> tyPrinter{ closed, ss };
-				cast->result->accept( tyPrinter );
-				visit_children = false;
-			}
-
-			/// Member access handled as function from aggregate to member
-			void previsit( UntypedMemberExpr* expr ) {
-				// TODO handle name extraction more generally
-				NameExpr* name = dynamic_cast<NameExpr*>(expr->member);
-
-				// fall back on just resolving call to member name
-				// TODO incorporate function type into resolv-proto
-				if ( ! name ) {
-					expr->member->accept( *visitor );
-					visit_children = false;
-					return;
-				}
-
-				rp_name( name->name, ss, "$field_" );
-				ss << "( ";
-				expr->aggregate->accept( *visitor );
-				ss << " )";
-				visit_children = false;
-			}
-
-			/// Constant expression replaced by its type
-			void previsit( ConstantExpr* expr ) {
-				PassVisitor<TypePrinter> tyPrinter{ closed, ss };
-				expr->constant.get_type()->accept( tyPrinter );
-				visit_children = false;
-			}
-
-			/// sizeof( ... ), alignof( ... ), offsetof( ... ) replaced by unsigned long constant
-			/// TODO extra expression to resolve argument
-			void previsit( SizeofExpr* ) {
-				ss << (int)BasicType::LongUnsignedInt;
-				visit_children = false;
-			}
-			void previsit( AlignofExpr* ) {
-				ss << (int)BasicType::LongUnsignedInt;
-				visit_children = false;
-			}
-			void previsit( UntypedOffsetofExpr* ) {
-				ss << (int)BasicType::LongUnsignedInt;
-				visit_children = false;
-			}
-
-			/// Logical expressions represented as operators
-			void previsit( LogicalExpr* expr ) {
-				ss << '$' << ( expr->get_isAnd() ? "and" : "or" ) << "( ";
-				expr->arg1->accept( *visitor );
-				ss << ' ';
-				expr->arg2->accept( *visitor );
-				ss << " )";
-				visit_children = false;
-			}
-
-			/// Conditional expression represented as operator
-			void previsit( ConditionalExpr* expr ) {
-				ss << "$if( ";
-				expr->arg1->accept( *visitor );
-				ss << ' ';
-				expr->arg2->accept( *visitor );
-				ss << ' ';
-				expr->arg3->accept( *visitor );
-				ss << " )";
-				visit_children = false;
-			}
-
-			/// Comma expression represented as operator
-			void previsit( CommaExpr* expr ) {
-				ss << "$seq( ";
-				expr->arg1->accept( *visitor );
-				ss << ' ';
-				expr->arg2->accept( *visitor );
-				ss << " )";
-				visit_children = false;
-			}
-
-			// TODO handle ignored ImplicitCopyCtorExpr and below
-		};
-
-		void build( Initializer* init, std::stringstream& ss ) {
-			if ( SingleInit* si = dynamic_cast<SingleInit*>(init) ) {
-				PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
-				si->value->accept( exprPrinter );
-				ss << ' ';
-			} else if ( ListInit* li = dynamic_cast<ListInit*>(init) ) {
-				for ( Initializer* it : li->initializers ) {
-					build( it, ss );
-				}
-			}
-		}
-
-		/// Adds an object initializer to the list of expressions
-		void build( const std::string& name, Initializer* init, std::stringstream& ss ) {
-			ss << "$constructor( &";
-			rp_name( name, ss );
-			ss << ' ';
-			build( init, ss );
-			ss << ')';
-		}
-
-		/// Adds a return expression to the list of expressions
-		void build( Type* rtnType, Expression* expr, std::stringstream& ss ) {
-			ss << "$constructor( ";
-			PassVisitor<TypePrinter> tyPrinter{ closed, ss };
-			rtnType->accept( tyPrinter );
-			ss << ' ';
-			PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
-			expr->accept( exprPrinter );
-			ss << " )";
-		}
-
-		/// Adds all named declarations in a list to the local scope
-		void addAll( const std::list<DeclarationWithType*>& decls ) {
-			for ( auto decl : decls ) {
-				// skip anonymous decls
-				if ( decl->name.empty() ) continue;
-
-				// handle objects
-				if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >( decl ) ) {
-					previsit( obj );
-				}
-			}
-		}
-
-		/// encode field access as function
-		void addAggregateFields( AggregateDecl* agg ) {
-			// make field names functions
-			for ( Declaration* member : agg->members ) {
-				if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >(member) ) {
-					std::stringstream ss;
-					build( obj->name, agg, obj->type, ss );
-					addDecl( ss.str() );
-				}
-			}
-
-			visit_children = false;
-		}
-
-	public:
-		void previsit( ObjectDecl *obj ) {
-			// add variable as declaration
-			std::stringstream ss;
-			build( obj->name, obj->type, ss );
-			addDecl( ss.str() );
-
-			// add initializer as expression if applicable
-			if ( obj->init ) {
-				std::stringstream ss;
-				build( obj->name, obj->init, ss );
-				addExpr( ss.str() );
-			}
-		}
-
-		void previsit( FunctionDecl *decl ) {
-			// skip decls with ftype parameters
-			for ( TypeDecl* tyvar : decl->type->forall ) {
-				if ( tyvar->get_kind() == TypeDecl::Ftype ) {
-					visit_children = false;
-					return;
-				}
-			}
-
-			// add function as declaration
-			std::stringstream ss;
-			build( decl->name, decl->type, ss );
-			addDecl( ss.str() );
-
-			// add body if available
-			if ( decl->statements ) {
-				std::list<Type*> rtns = from_decls( decl->type->returnVals );
-				Type* rtn = nullptr;
-				if ( rtns.size() == 1 ) {
-					if ( ! dynamic_cast<VoidType*>(rtns.front()) ) rtn = rtns.front()->clone();
-				} else if ( rtns.size() > 1 ) {
-					rtn = new TupleType{ Type::Qualifiers{}, rtns };
-				}
-				PassVisitor<ProtoDump> body{ this, rtn };
-
-				for ( TypeDecl* tyvar : decl->type->forall ) {
-					// add set of "closed" types to body so that it can print them as NamedType
-					body.pass.closed.insert( tyvar->name );
-
-					// add assertions to local scope as declarations as well
-					for ( DeclarationWithType* assn : tyvar->assertions ) {
-						assn->accept( body );
-					}
-				}
-
-				// add named parameters and returns to local scope
-				body.pass.addAll( decl->type->returnVals );
-				body.pass.addAll( decl->type->parameters );
-
-				// add contents of function to new scope
-				decl->statements->accept( body );
-
-				// store sub-scope
-				addSub( std::move(body) );
-			}
-
-			visit_children = false;
-		}
-
-		void previsit( StructDecl* sd ) { addAggregateFields(sd); }
-		void previsit( UnionDecl* ud ) { addAggregateFields(ud); }
-
-		void previsit( EnumDecl* ed ) {
-			std::unique_ptr<Type> eType =
-				std::make_unique<BasicType>( Type::Qualifiers{}, BasicType::SignedInt );
-
-			// add field names directly to enclosing scope
-			for ( Declaration* member : ed->members ) {
-				if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >(member) ) {
-					previsit(obj);
-				}
-			}
-
-			visit_children = false;
-		}
-
-		void previsit( ReturnStmt* stmt ) {
-			// do nothing for void-returning functions or statements returning nothing
-			if ( ! rtnType || ! stmt->expr ) return;
-
-			// otherwise construct the return type from the expression
-			std::stringstream ss;
-			build( rtnType.get(), stmt->expr, ss );
-			addExpr( ss.str() );
-			visit_children = false;
-		}
-
-		void previsit( AsmStmt* ) {
-			// skip asm statements
-			visit_children = false;
-		}
-
-		void previsit( Expression* expr ) {
-			std::stringstream ss;
-			PassVisitor<ExprPrinter> exPrinter{ closed, ss };
-			expr->accept( exPrinter );
-			addExpr( ss.str() );
-			visit_children = false;
-		}
-
-		/// Print non-prelude global declarations for resolv proto
-		void printGlobals() const {
-			std::cout << "#$ptr<T> $addr T" << std::endl;  // &?
-			int i = (int)BasicType::SignedInt;
-			std::cout << i << " $and " << i << ' ' << i << std::endl;  // ?&&?
-			std::cout << i << " $or " << i << ' ' << i << std::endl;  // ?||?
-			std::cout << "T $if " << i << " T T" << std::endl; // ternary operator
-			std::cout << "T $seq X T" << std::endl;  // ?,?
-		}
-
-	public:
-		/// Prints this ProtoDump instance
-		void print(unsigned indent = 0) const {
-			// print globals at root level
-			if ( ! parent ) printGlobals();
-			// print decls
-			std::string tab( indent, '\t' );
-			for ( const std::string& d : decls ) {
-				std::cout << tab << d << std::endl;
-			}
-			// print divider
-			std::cout << '\n' << tab << "%%\n" << std::endl;
-			// print top-level expressions
-			for ( const std::string& e : exprs ) {
-				std::cout << tab << e << std::endl;
-			}
-			// print child scopes
-			++indent;
-			for ( const ProtoDump & s : subs ) {
-				std::cout << tab << '{' << std::endl;
-				s.print( indent );
-				std::cout << tab << '}' << std::endl;
-			}
-		}
-	};
-
-	void dumpAsResolvProto( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<ProtoDump> dump;
-		acceptAll( translationUnit, dump );
-		dump.pass.print();
-	}
-
-}  // namespace CodeTools
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/CodeTools/ResolvProtoDump.h
===================================================================
--- src/CodeTools/ResolvProtoDump.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,33 +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.
-//
-// ResolvProtoDump.h -- Translates CFA resolver instances into resolv-proto instances
-//
-// Author           : Aaron Moss
-// Created On       : Tue Sep 11 09:04:00 2018
-// Last Modified By : Aaron Moss
-// Last Modified On : Tue Sep 11 09:04:00 2018
-// Update Count     : 1
-//
-
-#pragma once
-
-#include <list>
-
-class Declaration;
-
-namespace CodeTools {
-
-	/// Prints a translation unit in the input format of the resolv-proto tool
-	void dumpAsResolvProto( std::list< Declaration * > &translationUnit );
-
-}  // namespace CodeTools
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/CodeTools/TrackLoc.cc
===================================================================
--- src/CodeTools/TrackLoc.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,97 +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.
-//
-// TrackLoc.cc --
-//
-// Author           : Andrew Beach
-// Created On       : Tues May 2 15:46:00 2017
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri Nov 27 18:00:00 2020
-// Update Count     : 1
-//
-
-#include "TrackLoc.h"
-
-#include <cstdlib>                   // for exit, EXIT_FAILURE
-#include <iostream>                  // for operator<<, ostream, basic_ostream
-#include <iterator>                  // for back_inserter, inserter
-#include <stack>                     // for stack
-#include <string>                    // for operator<<, string
-#include <typeindex>                 // for type_index
-#include <vector>                    // for vector
-
-#include "Common/PassVisitor.h"      // for PassVisitor
-#include "Common/utility.h"          // for CodeLocation
-#include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
-#include "SynTree/Mutator.h"         // for mutateAll
-#include "SynTree/Visitor.h"         // for acceptAll
-
-class Declaration;
-
-namespace CodeTools {
-	class LocationPrinter {
-		size_t printLevel;
-
-		CodeLocation *lastNode;
-
-		std::stack< CodeLocation *, std::vector< CodeLocation * > > parents;
-	public:
-		LocationPrinter(size_t printLevel) :
-			printLevel(printLevel), lastNode(nullptr)
-		{}
-
-		void print( const std::string& name, BaseSyntaxNode *node) {
-			for (size_t i = 0 ; i < parents.size() ; ++i) {
-				std::cout << "    ";
-			}
-			if (2 <= printLevel) {
-				std::cout << name << '@';
-			}
-			std::cout << node->location << std::endl;
-		}
-
-		void atNode( BaseSyntaxNode *node ) {
-			std::string name = std::type_index(typeid(*node)).name();
-			if ( node->location.isUnset() ) {
-				if ( !parents.empty() ) {
-					node->location = *parents.top();
-				}
-				else if (nullptr != lastNode) {
-					node->location = *lastNode;
-				}
-				else {
-					assertf( false, "Top level node has no CodeLocation %s", toString( node ).c_str() );
-				}
-			}
-
-			if (0 < printLevel) {
-				print( name, node );
-			}
-			lastNode = &node->location;
-		}
-
-		void previsit(BaseSyntaxNode * node) {
-			atNode(node);
-			parents.push( &node->location );
-		}
-
-		void postvisit( __attribute__((unused)) BaseSyntaxNode * node ) {
-			parents.pop();
-		}
-
-	}; // LocationPrinter
-
-	void fillLocations( std::list< Declaration * > & translationUnit, size_t printLevel) {
-		PassVisitor<LocationPrinter> printer(printLevel);
-		acceptAll( translationUnit, printer );
-	}
-} // namespace CodeTools
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/CodeTools/TrackLoc.h
===================================================================
--- src/CodeTools/TrackLoc.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,36 +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.
-//
-// TrackLoc.h -- Track CodeLocation information in a translation unit's declarations.
-//
-// Author           : Andrew Beach
-// Created On       : Tues May 2 15:40:00 2017
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul 21 22:17:44 2017
-// Update Count     : 1
-//
-
-#pragma once
-
-#include <cstddef>   // for size_t
-#include <list>      // for list
-
-class Declaration;
-
-namespace CodeTools {
-
-	/// Fill in an approximate CodeLocation for each syntax node.
-	// printLevel: how much printing while filling in the node locations.
-	// 0 - No Printing, 1 - Print Location, 2 - Print Node Type and Location
-	void fillLocations( std::list< Declaration * > &translationUnit, size_t printLevel = 0 );
-
-}  // namespace CodeTools
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/CodeTools/module.mk
===================================================================
--- src/CodeTools/module.mk	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,23 +1,0 @@
-######################### -*- Mode: Makefile-Gmake -*- ########################
-##
-## 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.
-##
-## module.mk --
-##
-## Author           : Richard C. Bilson
-## Created On       : Mon Jun  1 17:49:17 2015
-## Last Modified By : Aaron Moss
-## Last Modified On : Wed Jan 31 16:36:00 2017
-## Update Count     : 2
-###############################################################################
-
-SRC += \
-	CodeTools/DeclStats.cc \
-	CodeTools/DeclStats.h \
-	CodeTools/ResolvProtoDump.cc \
-	CodeTools/ResolvProtoDump.h \
-	CodeTools/TrackLoc.cc \
-	CodeTools/TrackLoc.h
Index: src/Common/Eval.cc
===================================================================
--- src/Common/Eval.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Common/Eval.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -19,80 +19,8 @@
 
 #include "AST/Inspect.hpp"
-#include "Common/PassVisitor.h"
 #include "CodeGen/OperatorTable.h"						// access: OperatorInfo
 #include "AST/Pass.hpp"
 #include "InitTweak/InitTweak.h"
-#include "SynTree/Expression.h"
-
-//-------------------------------------------------------------
-// Old AST
-struct EvalOld : public WithShortCircuiting {
-	long long int value = 0;							// compose the result of the constant expression
-	bool valid = true;									// true => constant expression and value is the result
-														// false => not constant expression, e.g., ++i
-	bool cfavalid = true;								// true => constant expression and value computable
-														// false => constant expression but value not computable, e.g., sizeof(int)
-
-	void previsit( const BaseSyntaxNode * ) { visit_children = false; }
-	void postvisit( const BaseSyntaxNode * ) { valid = false; }
-
-	void postvisit( const SizeofExpr * ) {
-	}
-
-	void postvisit( const ConstantExpr * expr ) {
-		value = expr->intValue();
-	}
-
-	void postvisit( const CastExpr * expr ) {
-		auto arg = eval(expr->arg);
-		valid = arg.second;
-		value = arg.first;
-		// TODO: perform type conversion on value if valid
-	}
-
-	void postvisit( const VariableExpr * const expr ) {
-		if ( EnumInstType * inst = dynamic_cast<EnumInstType *>(expr->result) ) {
-			if ( EnumDecl * decl = inst->baseEnum ) {
-				if ( decl->valueOf( expr->var, value ) ) { // value filled by valueOf
-					return;
-				}
-			}
-		}
-		valid = false;
-	}
-
-	void postvisit( const ApplicationExpr * expr ) {
-		DeclarationWithType * function = InitTweak::getFunction(const_cast<ApplicationExpr *>(expr));
-		if ( ! function || function->linkage != LinkageSpec::Intrinsic ) { valid = false; return; }
-		const std::string & fname = function->name;
-		assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() );
-		std::pair<long long int, bool> arg1, arg2;
-		arg1 = eval(expr->args.front());
-		valid = valid && arg1.second;
-		if ( ! valid ) return;
-		if ( expr->args.size() == 2 ) {
-			arg2 = eval(expr->args.back());
-			valid = valid && arg2.second;
-			if ( ! valid ) return;
-		}
-		if (fname == "?+?") {
-			value = arg1.first + arg2.first;
-		} else if (fname == "?-?") {
-			value = arg1.first - arg2.first;
-		} else if (fname == "?*?") {
-			value = arg1.first * arg2.first;
-		} else if (fname == "?/?") {
-			value = arg1.first / arg2.first;
-		} else if (fname == "?%?") {
-			value = arg1.first % arg2.first;
-		} else {
-			valid = false;
-		}
-		// TODO: implement other intrinsic functions
-	}
-};
-
-//-------------------------------------------------------------
-// New AST
+
 struct EvalNew : public ast::WithShortCircuiting {
 	Evaluation result = { 0, true, true };
@@ -270,14 +198,4 @@
 };
 
-std::pair<long long int, bool> eval( const Expression * expr ) {
-	PassVisitor<EvalOld> ev;
-	if ( expr ) {
-		expr->accept( ev );
-		return std::make_pair( ev.pass.value, ev.pass.valid );
-	} else {
-		return std::make_pair( 0, false );
-	}
-}
-
 Evaluation eval( const ast::Expr * expr ) {
 	if ( expr ) {
Index: src/Common/Eval.h
===================================================================
--- src/Common/Eval.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Common/Eval.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -30,6 +30,4 @@
 
 /// Evaluates expr as a long long int.
-/// If second is false, expr could not be evaluated.
-std::pair<long long int, bool> eval(const Expression * expr);
 Evaluation eval(const ast::Expr * expr);
 
Index: src/Common/Examine.cc
===================================================================
--- src/Common/Examine.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Common/Examine.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -19,21 +19,4 @@
 #include "CodeGen/OperatorTable.h"
 #include "InitTweak/InitTweak.h"
-
-DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind ) {
-	if (func->name != "main") return nullptr;
-	if (func->type->parameters.size() != 1) return nullptr;
-
-	auto param = func->type->parameters.front();
-
-	auto type = dynamic_cast<ReferenceType * >(param->get_type());
-	if (!type) return nullptr;
-
-	auto obj = dynamic_cast<StructInstType *>(type->base);
-	if (!obj) return nullptr;
-
-	if (kind != obj->baseStruct->kind) return nullptr;
-
-	return param;
-}
 
 namespace {
@@ -69,16 +52,4 @@
 
 namespace {
-	Type * getDestructorParam( FunctionDecl * func ) {
-		if ( !CodeGen::isDestructor( func->name ) ) return nullptr;
-
-		auto params = func->type->parameters;
-		if ( 1 != params.size() ) return nullptr;
-
-		auto ref = dynamic_cast<ReferenceType *>( params.front()->get_type() );
-		if ( ref ) {
-			return ref->base;
-		}
-		return nullptr;
-	}
 
 const ast::Type * getDestructorParam( const ast::FunctionDecl * func ) {
@@ -88,12 +59,4 @@
 }
 
-}
-
-bool isDestructorFor( FunctionDecl * func, StructDecl * type_decl ) {
-	if ( Type * type = getDestructorParam( func ) ) {
-		auto stype = dynamic_cast<StructInstType *>( type );
-		return stype && stype->baseStruct == type_decl;
-	}
-	return false;
 }
 
Index: src/Common/Examine.h
===================================================================
--- src/Common/Examine.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Common/Examine.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -15,8 +15,6 @@
 
 #include "AST/Decl.hpp"
-#include "SynTree/Declaration.h"
 
 /// Check if this is a main function for a type of an aggregate kind.
-DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind );
 const ast::DeclWithType * isMainFor(
 	const ast::FunctionDecl * func, ast::AggregateDecl::Aggregate kind );
@@ -24,5 +22,4 @@
 
 /// Check if this function is a destructor for the given structure.
-bool isDestructorFor( FunctionDecl * func, StructDecl * type_decl );
 bool isDestructorFor(
 	const ast::FunctionDecl * func, const ast::StructDecl * type );
Index: c/Common/PassVisitor.cc
===================================================================
--- src/Common/PassVisitor.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,19 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// PassVisitor.cc --
-//
-// Author           : Thierry Delisle
-// Created On       : Fri Mar 03 14:53:53 2019
-// Last Modified By :
-// Last Modified On :
-// Update Count     :
-//
-
-#include "Common/PassVisitor.h"
-
-PassVisitorStats pass_visitor_stats;
-Stats::Counters::SimpleCounter* BaseSyntaxNode::new_nodes = nullptr;
Index: c/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,575 +1,0 @@
-#pragma once
-
-// IWYU pragma: private, include "Common/PassVisitor.h"
-
-#include <stack>
-#include <type_traits>
-
-#include "Common/Stats.h"
-#include "Common/utility.h"
-
-#include "SynTree/Mutator.h"
-#include "SynTree/Visitor.h"
-
-#include "SymTab/Indexer.h"
-
-#include "SynTree/Attribute.h"
-#include "SynTree/Initializer.h"
-#include "SynTree/Statement.h"
-#include "SynTree/Type.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/Expression.h"
-#include "SynTree/Constant.h"
-
-class TypeSubstitution;
-
-#include "PassVisitor.proto.h"
-
-//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-// Templated visitor type
-// To use declare a PassVisitor< YOUR VISITOR TYPE >
-// The visitor type should specify the previsit/postvisit/premutate/postmutate for types that are desired.
-// Note: previsit/postvisit/premutate/postmutate must be **public** members
-//
-// Several additional features are available through inheritance
-// | WithTypeSubstitution - provides polymorphic TypeSubstitution * env for the current expression
-// | WithStmtsToAdd       - provides the ability to insert statements before or after the current statement by adding new statements into
-//                          stmtsToAddBefore or stmtsToAddAfter respectively.
-// | WithShortCircuiting  - provides the ability to skip visiting child nodes; set visit_children to false in pre{visit,mutate} to skip visiting children
-// | WithGuards           - provides the ability to save/restore data like a LIFO stack; to save, call GuardValue with the variable to save, the variable
-//                          will automatically be restored to its previous value after the corresponding postvisit/postmutate teminates.
-//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-template< typename pass_type >
-class PassVisitor final : public Visitor, public Mutator {
-public:
-
-	template< typename... Args >
-	PassVisitor(Args &&... args)
-		: pass( std::forward<Args>( args )... )
-	{
-		typedef PassVisitor<pass_type> this_t;
-		this_t * const * visitor = visitor_impl(pass, 0);
-		if(visitor) {
-			*const_cast<this_t **>( visitor ) = this;
-		}
-	}
-
-	virtual ~PassVisitor() = default;
-
-	pass_type pass;
-
-	virtual void visit( ObjectDecl * objectDecl ) override final;
-	virtual void visit( const ObjectDecl * objectDecl ) override final;
-	virtual void visit( FunctionDecl * functionDecl ) override final;
-	virtual void visit( const FunctionDecl * functionDecl ) override final;
-	virtual void visit( StructDecl * aggregateDecl ) override final;
-	virtual void visit( const StructDecl * aggregateDecl ) override final;
-	virtual void visit( UnionDecl * aggregateDecl ) override final;
-	virtual void visit( const UnionDecl * aggregateDecl ) override final;
-	virtual void visit( EnumDecl * aggregateDecl ) override final;
-	virtual void visit( const EnumDecl * aggregateDecl ) override final;
-	virtual void visit( TraitDecl * aggregateDecl ) override final;
-	virtual void visit( const TraitDecl * aggregateDecl ) override final;
-	virtual void visit( TypeDecl * typeDecl ) override final;
-	virtual void visit( const TypeDecl * typeDecl ) override final;
-	virtual void visit( TypedefDecl * typeDecl ) override final;
-	virtual void visit( const TypedefDecl * typeDecl ) override final;
-	virtual void visit( AsmDecl * asmDecl ) override final;
-	virtual void visit( const AsmDecl * asmDecl ) override final;
-	virtual void visit( DirectiveDecl * directiveDecl ) override final;
-	virtual void visit( const DirectiveDecl * directiveDecl ) override final;
-	virtual void visit( StaticAssertDecl * assertDecl ) override final;
-	virtual void visit( const StaticAssertDecl * assertDecl ) override final;
-	virtual void visit( InlineMemberDecl * valueDecl ) override final;
-	virtual void visit( const InlineMemberDecl * valueDecl ) override final;
-
-	virtual void visit( CompoundStmt * compoundStmt ) override final;
-	virtual void visit( const CompoundStmt * compoundStmt ) override final;
-	virtual void visit( ExprStmt * exprStmt ) override final;
-	virtual void visit( const ExprStmt * exprStmt ) override final;
-	virtual void visit( AsmStmt * asmStmt ) override final;
-	virtual void visit( const AsmStmt * asmStmt ) override final;
-	virtual void visit( DirectiveStmt * dirStmt ) override final;
-	virtual void visit( const DirectiveStmt * dirStmt ) override final;
-	virtual void visit( IfStmt * ifStmt ) override final;
-	virtual void visit( const IfStmt * ifStmt ) override final;
-	virtual void visit( WhileDoStmt * whileDoStmt ) override final;
-	virtual void visit( const WhileDoStmt * whileDoStmt ) override final;
-	virtual void visit( ForStmt * forStmt ) override final;
-	virtual void visit( const ForStmt * forStmt ) override final;
-	virtual void visit( SwitchStmt * switchStmt ) override final;
-	virtual void visit( const SwitchStmt * switchStmt ) override final;
-	virtual void visit( CaseStmt * caseStmt ) override final;
-	virtual void visit( const CaseStmt * caseStmt ) override final;
-	virtual void visit( BranchStmt * branchStmt ) override final;
-	virtual void visit( const BranchStmt * branchStmt ) override final;
-	virtual void visit( ReturnStmt * returnStmt ) override final;
-	virtual void visit( const ReturnStmt * returnStmt ) override final;
-	virtual void visit( ThrowStmt * throwStmt ) override final;
-	virtual void visit( const ThrowStmt * throwStmt ) override final;
-	virtual void visit( TryStmt * tryStmt ) override final;
-	virtual void visit( const TryStmt * tryStmt ) override final;
-	virtual void visit( CatchStmt * catchStmt ) override final;
-	virtual void visit( const CatchStmt * catchStmt ) override final;
-	virtual void visit( FinallyStmt * finallyStmt ) override final;
-	virtual void visit( const FinallyStmt * finallyStmt ) override final;
-	virtual void visit( SuspendStmt * suspendStmt ) override final;
-	virtual void visit( const SuspendStmt * suspendStmt ) override final;
-	virtual void visit( WaitForStmt * waitforStmt ) override final;
-	virtual void visit( const WaitForStmt * waitforStmt ) override final;
-	virtual void visit( WithStmt * withStmt ) override final;
-	virtual void visit( const WithStmt * withStmt ) override final;
-	virtual void visit( NullStmt * nullStmt ) override final;
-	virtual void visit( const NullStmt * nullStmt ) override final;
-	virtual void visit( DeclStmt * declStmt ) override final;
-	virtual void visit( const DeclStmt * declStmt ) override final;
-	virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
-	virtual void visit( const ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
-	virtual void visit( MutexStmt * mutexStmt ) override final;
-	virtual void visit( const MutexStmt * mutexStmt ) override final;
-
-	virtual void visit( ApplicationExpr * applicationExpr ) override final;
-	virtual void visit( const ApplicationExpr * applicationExpr ) override final;
-	virtual void visit( UntypedExpr * untypedExpr ) override final;
-	virtual void visit( const UntypedExpr * untypedExpr ) override final;
-	virtual void visit( NameExpr * nameExpr ) override final;
-	virtual void visit( const NameExpr * nameExpr ) override final;
-	virtual void visit ( QualifiedNameExpr * qualifiedNameExpr ) override final;
-	virtual void visit ( const QualifiedNameExpr * qualifiedNameExpr ) override final;
-	virtual void visit( CastExpr * castExpr ) override final;
-	virtual void visit( const CastExpr * castExpr ) override final;
-	virtual void visit( KeywordCastExpr * castExpr ) override final;
-	virtual void visit( const KeywordCastExpr * castExpr ) override final;
-	virtual void visit( VirtualCastExpr * castExpr ) override final;
-	virtual void visit( const VirtualCastExpr * castExpr ) override final;
-	virtual void visit( AddressExpr * addressExpr ) override final;
-	virtual void visit( const AddressExpr * addressExpr ) override final;
-	virtual void visit( LabelAddressExpr * labAddressExpr ) override final;
-	virtual void visit( const LabelAddressExpr * labAddressExpr ) override final;
-	virtual void visit( UntypedMemberExpr * memberExpr ) override final;
-	virtual void visit( const UntypedMemberExpr * memberExpr ) override final;
-	virtual void visit( MemberExpr * memberExpr ) override final;
-	virtual void visit( const MemberExpr * memberExpr ) override final;
-	virtual void visit( VariableExpr * variableExpr ) override final;
-	virtual void visit( const VariableExpr * variableExpr ) override final;
-	virtual void visit( ConstantExpr * constantExpr ) override final;
-	virtual void visit( const ConstantExpr * constantExpr ) override final;
-	virtual void visit( SizeofExpr * sizeofExpr ) override final;
-	virtual void visit( const SizeofExpr * sizeofExpr ) override final;
-	virtual void visit( AlignofExpr * alignofExpr ) override final;
-	virtual void visit( const AlignofExpr * alignofExpr ) override final;
-	virtual void visit( UntypedOffsetofExpr * offsetofExpr ) override final;
-	virtual void visit( const UntypedOffsetofExpr * offsetofExpr ) override final;
-	virtual void visit( OffsetofExpr * offsetofExpr ) override final;
-	virtual void visit( const OffsetofExpr * offsetofExpr ) override final;
-	virtual void visit( OffsetPackExpr * offsetPackExpr ) override final;
-	virtual void visit( const OffsetPackExpr * offsetPackExpr ) override final;
-	virtual void visit( LogicalExpr * logicalExpr ) override final;
-	virtual void visit( const LogicalExpr * logicalExpr ) override final;
-	virtual void visit( ConditionalExpr * conditionalExpr ) override final;
-	virtual void visit( const ConditionalExpr * conditionalExpr ) override final;
-	virtual void visit( CommaExpr * commaExpr ) override final;
-	virtual void visit( const CommaExpr * commaExpr ) override final;
-	virtual void visit( TypeExpr * typeExpr ) override final;
-	virtual void visit( const TypeExpr * typeExpr ) override final;
-	virtual void visit( DimensionExpr * dimensionExpr ) override final;
-	virtual void visit( const DimensionExpr * dimensionExpr ) override final;
-	virtual void visit( AsmExpr * asmExpr ) override final;
-	virtual void visit( const AsmExpr * asmExpr ) override final;
-	virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override final;
-	virtual void visit( const ImplicitCopyCtorExpr * impCpCtorExpr ) override final;
-	virtual void visit( ConstructorExpr *  ctorExpr ) override final;
-	virtual void visit( const ConstructorExpr *  ctorExpr ) override final;
-	virtual void visit( CompoundLiteralExpr * compLitExpr ) override final;
-	virtual void visit( const CompoundLiteralExpr * compLitExpr ) override final;
-	virtual void visit( RangeExpr * rangeExpr ) override final;
-	virtual void visit( const RangeExpr * rangeExpr ) override final;
-	virtual void visit( UntypedTupleExpr * tupleExpr ) override final;
-	virtual void visit( const UntypedTupleExpr * tupleExpr ) override final;
-	virtual void visit( TupleExpr * tupleExpr ) override final;
-	virtual void visit( const TupleExpr * tupleExpr ) override final;
-	virtual void visit( TupleIndexExpr * tupleExpr ) override final;
-	virtual void visit( const TupleIndexExpr * tupleExpr ) override final;
-	virtual void visit( TupleAssignExpr * assignExpr ) override final;
-	virtual void visit( const TupleAssignExpr * assignExpr ) override final;
-	virtual void visit( StmtExpr *  stmtExpr ) override final;
-	virtual void visit( const StmtExpr *  stmtExpr ) override final;
-	virtual void visit( UniqueExpr *  uniqueExpr ) override final;
-	virtual void visit( const UniqueExpr *  uniqueExpr ) override final;
-	virtual void visit( UntypedInitExpr *  initExpr ) override final;
-	virtual void visit( const UntypedInitExpr *  initExpr ) override final;
-	virtual void visit( InitExpr *  initExpr ) override final;
-	virtual void visit( const InitExpr *  initExpr ) override final;
-	virtual void visit( DeletedExpr *  delExpr ) override final;
-	virtual void visit( const DeletedExpr *  delExpr ) override final;
-	virtual void visit( DefaultArgExpr * argExpr ) override final;
-	virtual void visit( const DefaultArgExpr * argExpr ) override final;
-	virtual void visit( GenericExpr * genExpr ) override final;
-	virtual void visit( const GenericExpr * genExpr ) override final;
-
-	virtual void visit( VoidType * basicType ) override final;
-	virtual void visit( const VoidType * basicType ) override final;
-	virtual void visit( BasicType * basicType ) override final;
-	virtual void visit( const BasicType * basicType ) override final;
-	virtual void visit( PointerType * pointerType ) override final;
-	virtual void visit( const PointerType * pointerType ) override final;
-	virtual void visit( ArrayType * arrayType ) override final;
-	virtual void visit( const ArrayType * arrayType ) override final;
-	virtual void visit( ReferenceType * referenceType ) override final;
-	virtual void visit( const ReferenceType * referenceType ) override final;
-	virtual void visit( QualifiedType * qualType ) override final;
-	virtual void visit( const QualifiedType * qualType ) override final;
-	virtual void visit( FunctionType * functionType ) override final;
-	virtual void visit( const FunctionType * functionType ) override final;
-	virtual void visit( StructInstType * aggregateUseType ) override final;
-	virtual void visit( const StructInstType * aggregateUseType ) override final;
-	virtual void visit( UnionInstType * aggregateUseType ) override final;
-	virtual void visit( const UnionInstType * aggregateUseType ) override final;
-	virtual void visit( EnumInstType * aggregateUseType ) override final;
-	virtual void visit( const EnumInstType * aggregateUseType ) override final;
-	virtual void visit( TraitInstType * aggregateUseType ) override final;
-	virtual void visit( const TraitInstType * aggregateUseType ) override final;
-	virtual void visit( TypeInstType * aggregateUseType ) override final;
-	virtual void visit( const TypeInstType * aggregateUseType ) override final;
-	virtual void visit( TupleType * tupleType ) override final;
-	virtual void visit( const TupleType * tupleType ) override final;
-	virtual void visit( TypeofType * typeofType ) override final;
-	virtual void visit( const TypeofType * typeofType ) override final;
-	virtual void visit( VTableType * vtableType ) override final;
-	virtual void visit( const VTableType * vtableType ) override final;
-	virtual void visit( AttrType * attrType ) override final;
-	virtual void visit( const AttrType * attrType ) override final;
-	virtual void visit( VarArgsType * varArgsType ) override final;
-	virtual void visit( const VarArgsType * varArgsType ) override final;
-	virtual void visit( ZeroType * zeroType ) override final;
-	virtual void visit( const ZeroType * zeroType ) override final;
-	virtual void visit( OneType * oneType ) override final;
-	virtual void visit( const OneType * oneType ) override final;
-	virtual void visit( GlobalScopeType * globalType ) override final;
-	virtual void visit( const GlobalScopeType * globalType ) override final;
-
-	virtual void visit( Designation * designation ) override final;
-	virtual void visit( const Designation * designation ) override final;
-	virtual void visit( SingleInit * singleInit ) override final;
-	virtual void visit( const SingleInit * singleInit ) override final;
-	virtual void visit( ListInit * listInit ) override final;
-	virtual void visit( const ListInit * listInit ) override final;
-	virtual void visit( ConstructorInit * ctorInit ) override final;
-	virtual void visit( const ConstructorInit * ctorInit ) override final;
-
-	virtual void visit( Constant * constant ) override final;
-	virtual void visit( const Constant * constant ) override final;
-
-	virtual void visit( Attribute * attribute ) override final;
-	virtual void visit( const Attribute * attribute ) override final;
-
-	virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override final;
-	virtual DeclarationWithType * mutate( FunctionDecl * functionDecl ) override final;
-	virtual Declaration * mutate( StructDecl * aggregateDecl ) override final;
-	virtual Declaration * mutate( UnionDecl * aggregateDecl ) override final;
-	virtual Declaration * mutate( EnumDecl * aggregateDecl ) override final;
-	virtual Declaration * mutate( TraitDecl * aggregateDecl ) override final;
-	virtual Declaration * mutate( TypeDecl * typeDecl ) override final;
-	virtual Declaration * mutate( TypedefDecl * typeDecl ) override final;
-	virtual AsmDecl * mutate( AsmDecl * asmDecl ) override final;
-	virtual DirectiveDecl * mutate( DirectiveDecl * directiveDecl ) override final;
-	virtual StaticAssertDecl * mutate( StaticAssertDecl * assertDecl ) override final;
-	virtual DeclarationWithType * mutate( InlineMemberDecl * valueDecl ) override final;
-
-	virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) override final;
-	virtual Statement * mutate( ExprStmt * exprStmt ) override final;
-	virtual Statement * mutate( AsmStmt * asmStmt ) override final;
-	virtual Statement * mutate( DirectiveStmt * dirStmt ) override final;
-	virtual Statement * mutate( IfStmt * ifStmt ) override final;
-	virtual Statement * mutate( WhileDoStmt * whileDoStmt ) override final;
-	virtual Statement * mutate( ForStmt * forStmt ) override final;
-	virtual Statement * mutate( SwitchStmt * switchStmt ) override final;
-	virtual Statement * mutate( CaseStmt * caseStmt ) override final;
-	virtual Statement * mutate( BranchStmt * branchStmt ) override final;
-	virtual Statement * mutate( ReturnStmt * returnStmt ) override final;
-	virtual Statement * mutate( ThrowStmt * throwStmt ) override final;
-	virtual Statement * mutate( TryStmt * tryStmt ) override final;
-	virtual Statement * mutate( CatchStmt * catchStmt ) override final;
-	virtual Statement * mutate( FinallyStmt * finallyStmt ) override final;
-	virtual Statement * mutate( SuspendStmt * suspendStmt ) override final;
-	virtual Statement * mutate( WaitForStmt * waitforStmt ) override final;
-	virtual Declaration * mutate( WithStmt * withStmt ) override final;
-	virtual NullStmt * mutate( NullStmt * nullStmt ) override final;
-	virtual Statement * mutate( DeclStmt * declStmt ) override final;
-	virtual Statement * mutate( ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
-	virtual Statement * mutate( MutexStmt * mutexStmt ) override final;
-
-	virtual Expression * mutate( ApplicationExpr * applicationExpr ) override final;
-	virtual Expression * mutate( UntypedExpr * untypedExpr ) override final;
-	virtual Expression * mutate( NameExpr * nameExpr ) override final;
-	virtual Expression * mutate( AddressExpr * addrExpr ) override final;
-	virtual Expression * mutate( LabelAddressExpr * labAddressExpr ) override final;
-	virtual Expression * mutate( CastExpr * castExpr ) override final;
-	virtual Expression * mutate( KeywordCastExpr * castExpr ) override final;
-	virtual Expression * mutate( VirtualCastExpr * castExpr ) override final;
-	virtual Expression * mutate( UntypedMemberExpr * memberExpr ) override final;
-	virtual Expression * mutate( MemberExpr * memberExpr ) override final;
-	virtual Expression * mutate( VariableExpr * variableExpr ) override final;
-	virtual Expression * mutate( ConstantExpr * constantExpr ) override final;
-	virtual Expression * mutate( SizeofExpr * sizeofExpr ) override final;
-	virtual Expression * mutate( AlignofExpr * alignofExpr ) override final;
-	virtual Expression * mutate( UntypedOffsetofExpr * offsetofExpr ) override final;
-	virtual Expression * mutate( OffsetofExpr * offsetofExpr ) override final;
-	virtual Expression * mutate( OffsetPackExpr * offsetPackExpr ) override final;
-	virtual Expression * mutate( LogicalExpr * logicalExpr ) override final;
-	virtual Expression * mutate( ConditionalExpr * conditionalExpr ) override final;
-	virtual Expression * mutate( CommaExpr * commaExpr ) override final;
-	virtual Expression * mutate( TypeExpr * typeExpr ) override final;
-	virtual Expression * mutate( DimensionExpr * dimensionExpr ) override final;
-	virtual Expression * mutate( AsmExpr * asmExpr ) override final;
-	virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override final;
-	virtual Expression * mutate( ConstructorExpr * ctorExpr ) override final;
-	virtual Expression * mutate( CompoundLiteralExpr * compLitExpr ) override final;
-	virtual Expression * mutate( RangeExpr * rangeExpr ) override final;
-	virtual Expression * mutate( UntypedTupleExpr * tupleExpr ) override final;
-	virtual Expression * mutate( TupleExpr * tupleExpr ) override final;
-	virtual Expression * mutate( TupleIndexExpr * tupleExpr ) override final;
-	virtual Expression * mutate( TupleAssignExpr * assignExpr ) override final; 
-	virtual Expression * mutate( StmtExpr *  stmtExpr ) override final;
-	virtual Expression * mutate( UniqueExpr *  uniqueExpr ) override final;
-	virtual Expression * mutate( UntypedInitExpr *  initExpr ) override final;
-	virtual Expression * mutate( InitExpr *  initExpr ) override final;
-	virtual Expression * mutate( DeletedExpr *  delExpr ) override final;
-	virtual Expression * mutate( DefaultArgExpr * argExpr ) override final;
-	virtual Expression * mutate( GenericExpr * genExpr ) override final;
-	virtual Expression * mutate( QualifiedNameExpr * qualifiedNameExpr ) override final;
-
-	virtual Type * mutate( VoidType * basicType ) override final;
-	virtual Type * mutate( BasicType * basicType ) override final;
-	virtual Type * mutate( PointerType * pointerType ) override final;
-	virtual Type * mutate( ArrayType * arrayType ) override final;
-	virtual Type * mutate( ReferenceType * referenceType ) override final;
-	virtual Type * mutate( QualifiedType * qualType ) override final;
-	virtual Type * mutate( FunctionType * functionType ) override final;
-	virtual Type * mutate( StructInstType * aggregateUseType ) override final;
-	virtual Type * mutate( UnionInstType * aggregateUseType ) override final;
-	virtual Type * mutate( EnumInstType * aggregateUseType ) override final;
-	virtual Type * mutate( TraitInstType * aggregateUseType ) override final;
-	virtual Type * mutate( TypeInstType * aggregateUseType ) override final;
-	virtual Type * mutate( TupleType * tupleType ) override final;
-	virtual Type * mutate( TypeofType * typeofType ) override final;
-	virtual Type * mutate( VTableType * vtableType ) override final;
-	virtual Type * mutate( AttrType * attrType ) override final;
-	virtual Type * mutate( VarArgsType * varArgsType ) override final;
-	virtual Type * mutate( ZeroType * zeroType ) override final;
-	virtual Type * mutate( OneType * oneType ) override final;
-	virtual Type * mutate( GlobalScopeType * globalType ) override final;
-
-	virtual Designation * mutate( Designation * designation ) override final;
-	virtual Initializer * mutate( SingleInit * singleInit ) override final;
-	virtual Initializer * mutate( ListInit * listInit ) override final;
-	virtual Initializer * mutate( ConstructorInit * ctorInit ) override final;
-
-	virtual Constant * mutate( Constant * constant ) override final;
-
-	virtual Attribute * mutate( Attribute * attribute ) override final;
-
-	virtual TypeSubstitution * mutate( TypeSubstitution * sub ) final;
-
-	bool isInFunction() const {
-		return inFunction;
-	}
-
-private:
-	bool inFunction = false;
-	bool atFunctionTop = false;
-
-	template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
-	template<typename pass_t> friend void acceptAll( const std::list< const Declaration * > &decls, PassVisitor< pass_t >& visitor );
-	template<typename pass_t> friend void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
-	template< typename TreeType, typename pass_t > friend void maybeAccept_impl( TreeType * tree, PassVisitor< pass_t > & visitor );
-	template< typename TreeType, typename pass_t > friend void maybeAccept_impl( const TreeType * tree, PassVisitor< pass_t > & visitor );
-	template< typename TreeType, typename pass_t > friend void maybeMutate_impl( TreeType *& tree, PassVisitor< pass_t > & mutator );
-	template< typename Container, typename pass_t > friend void maybeAccept_impl( Container & container, PassVisitor< pass_t > & visitor );
-	template< typename Container, typename pass_t > friend void maybeAccept_impl( const Container & container, PassVisitor< pass_t > & visitor );
-	template< typename Container, typename pass_t > friend void maybeMutate_impl( Container & container, PassVisitor< pass_t > & mutator );
-
-	template<typename node_type> void call_previsit ( node_type * node ) { previsit_impl ( pass, node, 0 ); }
-	template<typename node_type> void call_previsit ( const node_type * node ) { previsit_impl ( pass, node, 0 ); }
-	template<typename node_type> void call_postvisit( node_type * node ) { postvisit_impl( pass, node, 0 ); }
-	template<typename node_type> void call_postvisit( const node_type * node ) { postvisit_impl( pass, node, 0 ); }
-
-	template<typename node_type> void call_premutate ( node_type * node ) { premutate_impl( pass, node, 0 ); }
-	template<typename return_type, typename node_type> return_type call_postmutate ( node_type * node ) { return postmutate_impl<return_type>( pass, node, 0 ); }
-
-	void call_beginScope() { begin_scope_impl( pass, 0 ); }
-	void call_endScope  () { end_scope_impl  ( pass, 0 ); }
-
-	void set_env( TypeSubstitution * env ) { set_env_impl( pass, env, 0); }
-
-	template< typename func_t >
-	void handleStatementList( std::list< Statement * > & statements, func_t func );
-	void visitStatementList ( std::list< Statement* > &statements );
-	void mutateStatementList( std::list< Statement* > &statements );
-	void visitStatementList ( const std::list< Statement * > & statements );
-
-	template< typename func_t >
-	Statement * handleStatement( Statement * stmt, func_t func );
-	Statement * visitStatement ( Statement * stmt );
-	Statement * mutateStatement( Statement * stmt );
-	void visitStatement ( const Statement * stmt );
-
-	template< typename func_t >
-	Expression * handleExpression( Expression * expr, func_t func );
-	Expression * visitExpression ( Expression * expr );
-	Expression * mutateExpression( Expression * expr );
-	void visitExpression ( const Expression * expr );
-
-
-	auto			 		get_env_ptr    () -> decltype(env_impl( pass, 0)) { return env_impl( pass, 0); }
-	std::list< Statement* > * 	get_beforeStmts() { return stmtsToAddBefore_impl( pass, 0); }
-	std::list< Statement* > * 	get_afterStmts () { return stmtsToAddAfter_impl ( pass, 0); }
-	std::list< Declaration* > * 	get_beforeDecls() { return declsToAddBefore_impl( pass, 0); }
-	std::list< Declaration* > * 	get_afterDecls () { return declsToAddAfter_impl ( pass, 0); }
-
-	bool       get_visit_children    () { bool_ref * ptr = visit_children_impl(pass, 0); return ptr ? *ptr : true; }
-	bool_ref * get_visit_children_ptr() { return visit_children_impl(pass, 0); }
-
-	void indexerScopeEnter  ()                                    { indexer_impl_enterScope  ( pass, 0       ); }
-	void indexerScopeLeave  ()                                    { indexer_impl_leaveScope  ( pass, 0       ); }
-	void indexerAddId       ( const DeclarationWithType * node  ) { indexer_impl_addId       ( pass, 0, node ); }
-	void indexerAddType     ( const NamedTypeDecl       * node  ) { indexer_impl_addType     ( pass, 0, node ); }
-	void indexerAddStruct   ( const std::string         & id    ) { indexer_impl_addStruct   ( pass, 0, id   ); }
-	void indexerAddStruct   ( const StructDecl          * node  ) { indexer_impl_addStruct   ( pass, 0, node ); }
-	void indexerAddStructFwd( const StructDecl          * node  ) { indexer_impl_addStructFwd( pass, 0, node ); }
-	void indexerAddEnum     ( const EnumDecl            * node  ) { indexer_impl_addEnum     ( pass, 0, node ); }
-	void indexerAddUnion    ( const std::string         & id    ) { indexer_impl_addUnion    ( pass, 0, id   ); }
-	void indexerAddUnion    ( const UnionDecl           * node  ) { indexer_impl_addUnion    ( pass, 0, node ); }
-	void indexerAddUnionFwd ( const UnionDecl           * node  ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
-	void indexerAddTrait    ( const TraitDecl           * node  ) { indexer_impl_addTrait    ( pass, 0, node ); }
-	void indexerAddWith     ( const std::list< Expression * > & exprs, const Declaration * withStmt ) { indexer_impl_addWith( pass, 0, exprs, withStmt ); }
-
-
-	template< typename TreeType, typename VisitorType >
-	friend inline void indexerScopedAccept( TreeType * tree, VisitorType & visitor );
-
-	template< typename TreeType, typename VisitorType >
-	friend inline void indexerScopedAccept( const TreeType * tree, VisitorType & visitor );
-
-	template< typename TreeType, typename VisitorType >
-	friend inline void indexerScopedMutate( TreeType *& tree, VisitorType & visitor );
-};
-
-template<typename pass_type, typename T>
-void GuardValue( pass_type * pass, T& val ) {
-	pass->at_cleanup( [ val ]( void * newVal ) {
-		* static_cast< T * >( newVal ) = val;
-	}, static_cast< void * >( & val ) );
-}
-
-class WithTypeSubstitution {
-protected:
-	WithTypeSubstitution() = default;
-	~WithTypeSubstitution() = default;
-
-public:
-	TypeSubstitution * env = nullptr;
-};
-
-class WithConstTypeSubstitution {
-protected:
-	WithConstTypeSubstitution() = default;
-	~WithConstTypeSubstitution() = default;
-
-public:
-	const TypeSubstitution * env = nullptr;
-};
-
-class WithStmtsToAdd {
-protected:
-	WithStmtsToAdd() = default;
-	~WithStmtsToAdd() = default;
-
-public:
-	std::list< Statement* > stmtsToAddBefore;
-	std::list< Statement* > stmtsToAddAfter;
-};
-
-class WithDeclsToAdd {
-protected:
-	WithDeclsToAdd() = default;
-	~WithDeclsToAdd() {
-		assert( declsToAddBefore.empty() );
-	}
-
-public:
-	std::list< Declaration* > declsToAddBefore;
-	std::list< Declaration* > declsToAddAfter;
-};
-
-class WithShortCircuiting {
-protected:
-	WithShortCircuiting() = default;
-	~WithShortCircuiting() = default;
-
-public:
-	bool_ref visit_children;
-};
-
-class WithGuards {
-protected:
-	WithGuards() = default;
-	~WithGuards() = default;
-
-public:
-	at_cleanup_t at_cleanup;
-
-	template< typename T >
-	void GuardValue( T& val ) {
-		at_cleanup( [ val ]( void * newVal ) {
-			* static_cast< T * >( newVal ) = val;
-		}, static_cast< void * >( & val ) );
-	}
-
-	template< typename T >
-	void GuardScope( T& val ) {
-		val.beginScope();
-		at_cleanup( []( void * val ) {
-			static_cast< T * >( val )->endScope();
-		}, static_cast< void * >( & val ) );
-	}
-
-	template< typename Func >
-	void GuardAction( Func func ) {
-		at_cleanup( [func](__attribute__((unused)) void *) { func(); }, nullptr );
-	}
-};
-
-template<typename pass_type>
-class WithVisitorRef {
-protected:
-	WithVisitorRef() {}
-	~WithVisitorRef() {}
-
-public:
-	PassVisitor<pass_type> * const visitor = nullptr;
-
-	bool isInFunction() const {
-		return visitor->isInFunction();
-	}
-};
-
-class WithIndexer {
-protected:
-	WithIndexer( bool trackIdentifiers = true ) : indexer(trackIdentifiers) {}
-	~WithIndexer() {}
-
-public:
-	SymTab::Indexer indexer;
-};
-
-#include "Common/Stats.h"
-
-extern struct PassVisitorStats {
-	size_t depth = 0;
-	Stats::Counters::MaxCounter<double> * max = nullptr;
-	Stats::Counters::AverageCounter<double> * avg = nullptr;
-} pass_visitor_stats;
-
-#include "SynTree/TypeSubstitution.h"
-#include "PassVisitor.impl.h"
Index: c/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,4105 +1,0 @@
-#pragma once
-// IWYU pragma: private, include "PassVisitor.h"
-
-#define VISIT_START( node )                                     \
-	__attribute__((unused))                                   \
-	ChildrenGuard children_guard( get_visit_children_ptr() ); \
-	__attribute__((unused))                                   \
-	guard_value_impl guard( at_cleanup_impl(pass, 0) );       \
-	call_previsit( node );                                    \
-
-#define VISIT_END( node )                       \
-	call_postvisit( node );                   \
-
-#define MUTATE_START( node )                                    \
-	__attribute__((unused))                                   \
-	ChildrenGuard children_guard( get_visit_children_ptr() ); \
-	__attribute__((unused))                                   \
-	guard_value_impl guard( at_cleanup_impl(pass, 0) );       \
-	call_premutate( node );                                   \
-
-#define MUTATE_END( type, node )                \
-	auto __return = call_postmutate< type * >( node ); \
-	assert( __return ); \
-	return __return;
-
-
-template<typename T>
-static inline bool empty( T * ptr ) {
-	return !ptr || ptr->empty();
-}
-
-typedef std::list< Statement   * > StmtList_t;
-typedef std::list< Declaration * > DeclList_t;
-
-template<typename iterator_t>
-static inline void splice( iterator_t it, DeclList_t * decls ) {
-	std::transform(
-		decls->begin(),
-		decls->end(),
-		it,
-		[](Declaration * decl) -> auto {
-			return new DeclStmt( decl );
-		}
-	);
-	decls->clear();
-}
-
-template< typename pass_type >
-inline void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& visitor ) {
-	DeclList_t* beforeDecls = visitor.get_beforeDecls();
-	DeclList_t* afterDecls  = visitor.get_afterDecls();
-	SemanticErrorException errors;
-
-	pass_visitor_stats.depth++;
-	pass_visitor_stats.max->push(pass_visitor_stats.depth);
-	pass_visitor_stats.avg->push(pass_visitor_stats.depth);
-	for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
-
-
-		// splice in new declarations after previous decl
-		if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }
-
-		if ( i == decls.end() ) break;
-
-		try {
-			// run visitor on declaration
-			maybeAccept_impl( *i, visitor );
-		} catch( SemanticErrorException &e ) {
-			errors.append( e );
-		}
-
-		// splice in new declarations before current decl
-		if ( !empty( beforeDecls ) ) { decls.splice( i, *beforeDecls ); }
-	}
-	pass_visitor_stats.depth--;
-	if ( ! errors.isEmpty() ) {
-		throw errors;
-	}
-}
-
-template< typename pass_type >
-inline void acceptAll( const std::list< const Declaration * > & decls, PassVisitor< pass_type >& visitor ) {
-	SemanticErrorException errors;
-
-	pass_visitor_stats.depth++;
-	pass_visitor_stats.max->push(pass_visitor_stats.depth);
-	pass_visitor_stats.avg->push(pass_visitor_stats.depth);
-	for ( const Declaration * decl : decls ) {
-		try {
-			// run visitor on declaration
-			maybeAccept_impl( decl, visitor );
-		}
-		catch( SemanticErrorException &e ) {
-			errors.append( e );
-		}
-	}
-	pass_visitor_stats.depth--;
-	if ( ! errors.isEmpty() ) {
-		throw errors;
-	}
-}
-
-template< typename pass_type >
-inline void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& mutator ) {
-	DeclList_t* beforeDecls = mutator.get_beforeDecls();
-	DeclList_t* afterDecls  = mutator.get_afterDecls();
-	SemanticErrorException errors;
-
-	pass_visitor_stats.depth++;
-	pass_visitor_stats.max->push(pass_visitor_stats.depth);
-	pass_visitor_stats.avg->push(pass_visitor_stats.depth);
-	for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
-		// splice in new declarations after previous decl
-		if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }
-
-		if ( i == decls.end() ) break;
-		try {
-			// run mutator on declaration
-			maybeMutate_impl( *i, mutator );
-		} catch( SemanticErrorException &e ) {
-			errors.append( e );
-		}
-
-		// splice in new declarations before current decl
-		if ( !empty( beforeDecls ) ) { decls.splice( i, *beforeDecls ); }
-	}
-	pass_visitor_stats.depth--;
-	if ( ! errors.isEmpty() ) {
-		throw errors;
-	}
-}
-
-template< typename TreeType, typename pass_type >
-inline void maybeAccept_impl( TreeType * tree, PassVisitor< pass_type > & visitor ) {
-	if ( ! visitor.get_visit_children() ) return;
-	if ( tree ) {
-		tree->accept( visitor );
-	}
-}
-
-template< typename TreeType, typename pass_type >
-inline void maybeAccept_impl( const TreeType * tree, PassVisitor< pass_type > & visitor ) {
-	if ( ! visitor.get_visit_children() ) return;
-	if ( tree ) {
-		tree->accept( visitor );
-	}
-}
-
-template< typename Container, typename pass_type >
-inline void maybeAccept_impl( Container & container, PassVisitor< pass_type > & visitor ) {
-	if ( ! visitor.get_visit_children() ) return;
-	SemanticErrorException errors;
-
-	pass_visitor_stats.depth++;
-	pass_visitor_stats.max->push(pass_visitor_stats.depth);
-	pass_visitor_stats.avg->push(pass_visitor_stats.depth);
-	for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
-		try {
-			if ( *i ) {
-				(*i)->accept( visitor );
-			}
-		} catch( SemanticErrorException &e ) {
-			errors.append( e );
-		}
-	}
-	pass_visitor_stats.depth--;
-	if ( ! errors.isEmpty() ) {
-		throw errors;
-	}
-}
-
-template< typename Container, typename pass_type >
-inline void maybeAccept_impl( const Container & container, PassVisitor< pass_type > & visitor ) {
-	if ( ! visitor.get_visit_children() ) return;
-	SemanticErrorException errors;
-
-	pass_visitor_stats.depth++;
-	pass_visitor_stats.max->push(pass_visitor_stats.depth);
-	pass_visitor_stats.avg->push(pass_visitor_stats.depth);
-	for ( const auto & i : container ) {
-		try {
-			if ( i ) {
-				i->accept( visitor );
-			}
-		} catch( SemanticErrorException &e ) {
-			errors.append( e );
-		}
-	}
-	pass_visitor_stats.depth--;
-	if ( ! errors.isEmpty() ) {
-		throw errors;
-	}
-}
-
-template< typename TreeType, typename pass_type >
-inline void maybeMutate_impl( TreeType *& tree, PassVisitor< pass_type > & mutator ) {
-	if ( ! mutator.get_visit_children() ) return;
-
-	if ( tree ) {
-		tree = strict_dynamic_cast< TreeType * >( tree->acceptMutator( mutator ) );
-	}
-}
-
-template< typename Container, typename pass_type >
-inline void maybeMutate_impl( Container & container, PassVisitor< pass_type > & mutator ) {
-
-	if ( ! mutator.get_visit_children() ) return;
-	SemanticErrorException errors;
-
-	pass_visitor_stats.depth++;
-	pass_visitor_stats.max->push(pass_visitor_stats.depth);
-	pass_visitor_stats.avg->push(pass_visitor_stats.depth);
-	for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
-		try {
-			if ( *i ) {
-				*i = dynamic_cast< typename Container::value_type >( (*i)->acceptMutator( mutator ) );
-				assert( *i );
-			} // if
-		} catch( SemanticErrorException &e ) {
-			errors.append( e );
-		} // try
-	} // for
-	pass_visitor_stats.depth--;
-	if ( ! errors.isEmpty() ) {
-		throw errors;
-	} // if
-}
-
-template< typename pass_type >
-template< typename func_t >
-void PassVisitor< pass_type >::handleStatementList( std::list< Statement * > & statements, func_t func ) {
-	if ( ! get_visit_children() ) return;
-	SemanticErrorException errors;
-
-	// don't want statements from outer CompoundStmts to be added to this CompoundStmt
-	ValueGuardPtr< StmtList_t > oldBeforeStmts( get_beforeStmts() );
-	ValueGuardPtr< StmtList_t > oldAfterStmts ( get_afterStmts () );
-	ValueGuardPtr< DeclList_t > oldBeforeDecls( get_beforeDecls() );
-	ValueGuardPtr< DeclList_t > oldAfterDecls ( get_afterDecls () );
-
-	StmtList_t* beforeStmts = get_beforeStmts();
-	StmtList_t* afterStmts  = get_afterStmts();
-	DeclList_t* beforeDecls = get_beforeDecls();
-	DeclList_t* afterDecls  = get_afterDecls();
-
-	pass_visitor_stats.depth++;
-	pass_visitor_stats.max->push(pass_visitor_stats.depth);
-	pass_visitor_stats.avg->push(pass_visitor_stats.depth);
-	for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {
-
-		if ( !empty( afterDecls ) ) { splice( std::inserter( statements, i ), afterDecls ); }
-		if ( !empty( afterStmts ) ) { statements.splice( i, *afterStmts ); }
-
-		try {
-			func( *i );
-			assert( *i );
-			assert(( empty( beforeStmts ) && empty( afterStmts ))
-			    || ( empty( beforeDecls ) && empty( afterDecls )) );
-
-		} catch ( SemanticErrorException &e ) {
-			errors.append( e );
-		}
-
-		if ( !empty( beforeDecls ) ) { splice( std::inserter( statements, i ), beforeDecls ); }
-		if ( !empty( beforeStmts ) ) { statements.splice( i, *beforeStmts ); }
-	}
-	pass_visitor_stats.depth--;
-
-	if ( !empty( afterDecls ) ) { splice( std::back_inserter( statements ), afterDecls); }
-	if ( !empty( afterStmts ) ) { statements.splice( statements.end(), *afterStmts ); }
-	if ( !errors.isEmpty() ) { throw errors; }
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visitStatementList( std::list< Statement * > & statements ) {
-	handleStatementList( statements, [this]( Statement * stmt) {
-		maybeAccept_impl( stmt, *this );
-	});
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visitStatementList( const std::list< Statement * > & statements ) {
-	if ( ! get_visit_children() ) return;
-	SemanticErrorException errors;
-
-	pass_visitor_stats.depth++;
-	pass_visitor_stats.max->push(pass_visitor_stats.depth);
-	pass_visitor_stats.avg->push(pass_visitor_stats.depth);
-	for ( const Statement * i : statements ) {
-		try {
-			maybeAccept_impl( i, *this );
-		} catch ( SemanticErrorException &e ) {
-			errors.append( e );
-		}
-	}
-	pass_visitor_stats.depth--;
-	if ( !errors.isEmpty() ) { throw errors; }
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::mutateStatementList( std::list< Statement * > & statements ) {
-	handleStatementList( statements, [this]( Statement *& stmt) {
-		maybeMutate_impl( stmt, *this );
-	});
-}
-
-
-template< typename pass_type >
-template< typename func_t >
-Statement * PassVisitor< pass_type >::handleStatement( Statement * stmt, func_t func ) {
-	if ( ! get_visit_children() ) return stmt;
-
-	// don't want statements from outer CompoundStmts to be added to this CompoundStmt
-	ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
-	ValueGuardPtr< DeclList_t >          oldBeforeDecls( get_beforeDecls() );
-	ValueGuardPtr< DeclList_t >          oldAfterDecls ( get_afterDecls () );
-	ValueGuardPtr< StmtList_t >          oldBeforeStmts( get_beforeStmts() );
-	ValueGuardPtr< StmtList_t >          oldAfterStmts ( get_afterStmts () );
-
-	Statement *newStmt = func( stmt );
-
-	StmtList_t* beforeStmts = get_beforeStmts();
-	StmtList_t* afterStmts  = get_afterStmts();
-	DeclList_t* beforeDecls = get_beforeDecls();
-	DeclList_t* afterDecls  = get_afterDecls();
-
-	if( empty(beforeStmts) && empty(afterStmts) && empty(beforeDecls) && empty(afterDecls) ) { return newStmt; }
-	assert(( empty( beforeStmts ) && empty( afterStmts ))
-	    || ( empty( beforeDecls ) && empty( afterDecls )) );
-
-	CompoundStmt *compound = new CompoundStmt();
-	if( !empty(beforeDecls) ) { splice( std::back_inserter( compound->get_kids() ), beforeDecls ); }
-	if( !empty(beforeStmts) ) { compound->get_kids().splice( compound->get_kids().end(), *beforeStmts ); }
-	compound->get_kids().push_back( newStmt );
-	if( !empty(afterDecls) ) { splice( std::back_inserter( compound->get_kids() ), afterDecls ); }
-	if( !empty(afterStmts) ) { compound->get_kids().splice( compound->get_kids().end(), *afterStmts ); }
-	return compound;
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::visitStatement( Statement * stmt ) {
-	return handleStatement( stmt, [this]( Statement * stmt ) {
-		maybeAccept_impl( stmt, *this );
-		return stmt;
-	});
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visitStatement( const Statement * stmt ) {
-	if ( ! get_visit_children() ) return;
-
-	// don't want statements from outer CompoundStmts to be added to this CompoundStmt
-	ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
-
-	maybeAccept_impl( stmt, *this );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutateStatement( Statement * stmt ) {
-	return handleStatement( stmt, [this]( Statement * stmt ) {
-		maybeMutate_impl( stmt, *this );
-		return stmt;
-	});
-}
-
-template< typename pass_type >
-template< typename func_t >
-Expression * PassVisitor< pass_type >::handleExpression( Expression * expr, func_t func ) {
-	if ( ! get_visit_children() ) return expr;
-	if( !expr ) return nullptr;
-
-	auto env_ptr = get_env_ptr();
-	if ( env_ptr && expr->get_env() ) {
-		*env_ptr = expr->get_env();
-	}
-
-	// should env be moved onto the result of the mutate?
-	return func( expr );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::visitExpression( Expression * expr ) {
-	return handleExpression(expr, [this]( Expression * expr ) {
-		maybeAccept_impl( expr, *this );
-		return expr;
-	});
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visitExpression( const Expression * expr ) {
-	if ( ! get_visit_children() ) return;
-	if( !expr ) return;
-
-	auto env_ptr = get_env_ptr();
-	if ( env_ptr && expr->get_env() ) {
-		*env_ptr = expr->get_env();
-	}
-
-	maybeAccept_impl( expr, *this );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutateExpression( Expression * expr ) {
-	return handleExpression(expr, [this]( Expression * expr ) {
-		maybeMutate_impl( expr, *this );
-		return expr;
-	});
-}
-
-template< typename TreeType, typename VisitorType >
-inline void indexerScopedAccept( TreeType * tree, VisitorType & visitor ) {
-	if ( ! visitor.get_visit_children() ) return;
-	auto guard = makeFuncGuard(
-		[&visitor]() { visitor.indexerScopeEnter(); },
-		[&visitor]() { visitor.indexerScopeLeave(); }
-	);
-	maybeAccept_impl( tree, visitor );
-}
-
-template< typename TreeType, typename VisitorType >
-inline void indexerScopedAccept( const TreeType * tree, VisitorType & visitor ) {
-	if ( ! visitor.get_visit_children() ) return;
-	auto guard = makeFuncGuard(
-		[&visitor]() { visitor.indexerScopeEnter(); },
-		[&visitor]() { visitor.indexerScopeLeave(); }
-	);
-	maybeAccept_impl( tree, visitor );
-}
-
-template< typename TreeType, typename MutatorType >
-inline void indexerScopedMutate( TreeType *& tree, MutatorType & mutator ) {
-	if ( ! mutator.get_visit_children() ) return;
-	auto guard = makeFuncGuard(
-		[&mutator]() { mutator.indexerScopeEnter(); },
-		[&mutator]() { mutator.indexerScopeLeave(); }
-	);
-	maybeMutate_impl( tree, mutator );
-}
-
-//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-//========================================================================================================================================================================
-//========================================================================================================================================================================
-//========================================================================================================================================================================
-//========================================================================================================================================================================
-//========================================================================================================================================================================
-//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-// A NOTE ON THE ORDER OF TRAVERSAL
-//
-// Types and typedefs have their base types visited before they are added to the type table.  This is ok, since there is
-// no such thing as a recursive type or typedef.
-//
-//             typedef struct { T *x; } T; // never allowed
-//
-// for structs/unions, it is possible to have recursion, so the decl should be added as if it's incomplete to begin, the
-// members are traversed, and then the complete type should be added (assuming the type is completed by this particular
-// declaration).
-//
-//             struct T { struct T *x; }; // allowed
-//
-// It is important to add the complete type to the symbol table *after* the members/base has been traversed, since that
-// traversal may modify the definition of the type and these modifications should be visible when the symbol table is
-// queried later in this pass.
-//
-// TODO: figure out whether recursive contexts are sensible/possible/reasonable.
-
-//--------------------------------------------------------------------------
-// ObjectDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ObjectDecl * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->type         , *this );
-	maybeAccept_impl   ( node->init         , *this );
-	maybeAccept_impl   ( node->bitfieldWidth, *this );
-	maybeAccept_impl   ( node->attributes   , *this );
-
-	indexerAddId( node );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ObjectDecl * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->type         , *this );
-	maybeAccept_impl( node->init         , *this );
-	maybeAccept_impl( node->bitfieldWidth, *this );
-	maybeAccept_impl( node->attributes   , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-DeclarationWithType * PassVisitor< pass_type >::mutate( ObjectDecl * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->type         , *this );
-	maybeMutate_impl   ( node->init         , *this );
-	maybeMutate_impl   ( node->bitfieldWidth, *this );
-	maybeMutate_impl   ( node->attributes   , *this );
-
-	indexerAddId( node );
-
-	MUTATE_END( DeclarationWithType, node );
-}
-
-//--------------------------------------------------------------------------
-// FunctionDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( FunctionDecl * node ) {
-	VISIT_START( node );
-
-	indexerAddId( node );
-
-	maybeAccept_impl( node->withExprs, *this );
-	{
-		// with clause introduces a level of scope (for the with expression members).
-		// with clause exprs are added to the indexer before parameters so that parameters
-		// shadow with exprs and not the other way around.
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		indexerAddWith( node->withExprs, node );
-		{
-			auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-			// implicit add __func__ identifier as specified in the C manual 6.4.2.2
-			static ObjectDecl func(
-				"__func__", noStorageClasses, LinkageSpec::C, nullptr,
-				new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), nullptr, true, false ),
-				nullptr
-			);
-			indexerAddId( &func );
-			maybeAccept_impl( node->type, *this );
-			// First remember that we are now within a function.
-			ValueGuard< bool > oldInFunction( inFunction );
-			inFunction = true;
-			// The function body needs to have the same scope as parameters.
-			// A CompoundStmt will not enter a new scope if atFunctionTop is true.
-			ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
-			atFunctionTop = true;
-			maybeAccept_impl( node->statements, *this );
-			maybeAccept_impl( node->attributes, *this );
-		}
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const FunctionDecl * node ) {
-	VISIT_START( node );
-
-	indexerAddId( node );
-
-	maybeAccept_impl( node->withExprs, *this );
-	{
-		// with clause introduces a level of scope (for the with expression members).
-		// with clause exprs are added to the indexer before parameters so that parameters
-		// shadow with exprs and not the other way around.
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		indexerAddWith( node->withExprs, node );
-		{
-			auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-			// implicit add __func__ identifier as specified in the C manual 6.4.2.2
-			static ObjectDecl func(
-				"__func__", noStorageClasses, LinkageSpec::C, nullptr,
-				new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), nullptr, true, false ),
-				nullptr
-			);
-			indexerAddId( &func );
-			maybeAccept_impl( node->type, *this );
-			// First remember that we are now within a function.
-			ValueGuard< bool > oldInFunction( inFunction );
-			inFunction = true;
-			// The function body needs to have the same scope as parameters.
-			// A CompoundStmt will not enter a new scope if atFunctionTop is true.
-			ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
-			atFunctionTop = true;
-			maybeAccept_impl( node->statements, *this );
-			maybeAccept_impl( node->attributes, *this );
-		}
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-DeclarationWithType * PassVisitor< pass_type >::mutate( FunctionDecl * node ) {
-	MUTATE_START( node );
-
-	indexerAddId( node );
-
-	{
-		// with clause introduces a level of scope (for the with expression members).
-		// with clause exprs are added to the indexer before parameters so that parameters
-		// shadow with exprs and not the other way around.
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		indexerAddWith( node->withExprs, node );
-		{
-			auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-			// implicit add __func__ identifier as specified in the C manual 6.4.2.2
-			static ObjectDecl func(
-				"__func__", noStorageClasses, LinkageSpec::C, nullptr,
-				new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), nullptr, true, false ),
-				nullptr
-			);
-			indexerAddId( &func );
-			maybeMutate_impl( node->type, *this );
-			maybeMutate_impl( node->attributes, *this );
-			// First remember that we are now within a function.
-			ValueGuard< bool > oldInFunction( inFunction );
-			inFunction = true;
-			// The function body needs to have the same scope as parameters.
-			// A CompoundStmt will not enter a new scope if atFunctionTop is true.
-			ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
-			atFunctionTop = true;
-			maybeMutate_impl( node->statements, *this );
-		}
-	}
-
-	MUTATE_END( DeclarationWithType, node );
-}
-
-//--------------------------------------------------------------------------
-// StructDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( StructDecl * node ) {
-	VISIT_START( node );
-
-	// make up a forward declaration and add it before processing the members
-	// needs to be on the heap because addStruct saves the pointer
-	indexerAddStructFwd( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->parameters, *this );
-		maybeAccept_impl( node->members   , *this );
-		maybeAccept_impl( node->attributes, *this );
-	}
-
-	// this addition replaces the forward declaration
-	indexerAddStruct( node );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const StructDecl * node ) {
-	VISIT_START( node );
-
-	// make up a forward declaration and add it before processing the members
-	// needs to be on the heap because addStruct saves the pointer
-	indexerAddStructFwd( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->parameters, *this );
-		maybeAccept_impl( node->members   , *this );
-		maybeAccept_impl( node->attributes, *this );
-	}
-
-	// this addition replaces the forward declaration
-	indexerAddStruct( node );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( StructDecl * node ) {
-	MUTATE_START( node );
-
-	// make up a forward declaration and add it before processing the members
-	// needs to be on the heap because addStruct saves the pointer
-	indexerAddStructFwd( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->parameters, *this );
-		maybeMutate_impl( node->members   , *this );
-		maybeMutate_impl( node->attributes, *this );
-	}
-
-	// this addition replaces the forward declaration
-	indexerAddStruct( node );
-
-	MUTATE_END( Declaration, node );
-}
-
-//--------------------------------------------------------------------------
-// UnionDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( UnionDecl * node ) {
-	VISIT_START( node );
-
-	// make up a forward declaration and add it before processing the members
-	indexerAddUnionFwd( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->parameters, *this );
-		maybeAccept_impl( node->members   , *this );
-		maybeAccept_impl( node->attributes, *this );
-	}
-
-	indexerAddUnion( node );
-
-	VISIT_END( node );
-}
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const UnionDecl * node ) {
-	VISIT_START( node );
-
-	// make up a forward declaration and add it before processing the members
-	indexerAddUnionFwd( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->parameters, *this );
-		maybeAccept_impl( node->members   , *this );
-		maybeAccept_impl( node->attributes, *this );
-	}
-
-	indexerAddUnion( node );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( UnionDecl * node ) {
-	MUTATE_START( node );
-
-	// make up a forward declaration and add it before processing the members
-	indexerAddUnionFwd( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->parameters, *this );
-		maybeMutate_impl( node->members   , *this );
-		maybeMutate_impl( node->attributes, *this );
-	}
-
-	indexerAddUnion( node );
-
-	MUTATE_END( Declaration, node );
-}
-
-//--------------------------------------------------------------------------
-// EnumDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( EnumDecl * node ) {
-	VISIT_START( node );
-
-	indexerAddEnum( node );
-
-	// unlike structs, traits, and unions, enums inject their members into the global scope
-	// if ( node->base ) maybeAccept_impl( node->base, *this ); // Need this? Maybe not?
-	maybeAccept_impl( node->parameters, *this );
-	maybeAccept_impl( node->members   , *this );
-	maybeAccept_impl( node->attributes, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const EnumDecl * node ) {
-	VISIT_START( node );
-
-	indexerAddEnum( node );
-
-	// unlike structs, traits, and unions, enums inject their members into the global scope
-	maybeAccept_impl( node->parameters, *this );
-	maybeAccept_impl( node->members   , *this );
-	maybeAccept_impl( node->attributes, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( EnumDecl * node ) {
-	MUTATE_START( node );
-
-	indexerAddEnum( node );
-
-	// unlike structs, traits, and unions, enums inject their members into the global scope
-	maybeMutate_impl( node->parameters, *this );
-	maybeMutate_impl( node->members   , *this );
-	maybeMutate_impl( node->attributes, *this );
-
-	MUTATE_END( Declaration, node );
-}
-
-//--------------------------------------------------------------------------
-// TraitDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TraitDecl * node ) {
-	VISIT_START( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->parameters, *this );
-		maybeAccept_impl( node->members   , *this );
-		maybeAccept_impl( node->attributes, *this );
-	}
-
-	indexerAddTrait( node );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TraitDecl * node ) {
-	VISIT_START( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->parameters, *this );
-		maybeAccept_impl( node->members   , *this );
-		maybeAccept_impl( node->attributes, *this );
-	}
-
-	indexerAddTrait( node );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( TraitDecl * node ) {
-	MUTATE_START( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->parameters, *this );
-		maybeMutate_impl( node->members   , *this );
-		maybeMutate_impl( node->attributes, *this );
-	}
-
-	indexerAddTrait( node );
-
-	MUTATE_END( Declaration, node );
-}
-
-//--------------------------------------------------------------------------
-// TypeDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TypeDecl * node ) {
-	VISIT_START( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->base      , *this );
-	}
-
-	// see A NOTE ON THE ORDER OF TRAVERSAL, above
-	// note that assertions come after the type is added to the symtab, since they are not part of the type proper
-	// and may depend on the type itself
-	indexerAddType( node );
-
-	maybeAccept_impl( node->assertions, *this );
-
-	indexerScopedAccept( node->init, *this );
-
-	VISIT_END( node );
-}
-
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TypeDecl * node ) {
-	VISIT_START( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->base      , *this );
-	}
-
-	// see A NOTE ON THE ORDER OF TRAVERSAL, above
-	// note that assertions come after the type is added to the symtab, since they are not part of the type proper
-	// and may depend on the type itself
-	indexerAddType( node );
-
-	maybeAccept_impl( node->assertions, *this );
-
-	indexerScopedAccept( node->init, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( TypeDecl * node ) {
-	MUTATE_START( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->base      , *this );
-	}
-
-	// see A NOTE ON THE ORDER OF TRAVERSAL, above
-	// note that assertions come after the type is added to the symtab, since they are not part of the type proper
-	// and may depend on the type itself
-	indexerAddType( node );
-
-	maybeMutate_impl( node->assertions, *this );
-
-	indexerScopedMutate( node->init, *this );
-
-	MUTATE_END( Declaration, node );
-}
-
-//--------------------------------------------------------------------------
-// TypedefDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TypedefDecl * node ) {
-	VISIT_START( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->base      , *this );
-	}
-
-	indexerAddType( node );
-
-	maybeAccept_impl( node->assertions, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TypedefDecl * node ) {
-	VISIT_START( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->base      , *this );
-	}
-
-	indexerAddType( node );
-
-	maybeAccept_impl( node->assertions, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( TypedefDecl * node ) {
-	MUTATE_START( node );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->base      , *this );
-	}
-
-	indexerAddType( node );
-
-	maybeMutate_impl( node->assertions, *this );
-
-	MUTATE_END( Declaration, node );
-}
-
-//--------------------------------------------------------------------------
-// AsmDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( AsmDecl * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->stmt, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const AsmDecl * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->stmt, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-AsmDecl * PassVisitor< pass_type >::mutate( AsmDecl * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->stmt, *this );
-
-	MUTATE_END( AsmDecl, node );
-}
-
-//--------------------------------------------------------------------------
-// DirectiveDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( DirectiveDecl * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->stmt, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const DirectiveDecl * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->stmt, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-DirectiveDecl * PassVisitor< pass_type >::mutate( DirectiveDecl * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->stmt, *this );
-
-	MUTATE_END( DirectiveDecl, node );
-}
-
-//--------------------------------------------------------------------------
-// StaticAssertDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( StaticAssertDecl * node ) {
-	VISIT_START( node );
-
-	node->condition = visitExpression( node->condition );
-	maybeAccept_impl( node->message, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const StaticAssertDecl * node ) {
-	VISIT_START( node );
-
-	visitExpression( node->condition );
-	maybeAccept_impl( node->message, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-StaticAssertDecl * PassVisitor< pass_type >::mutate( StaticAssertDecl * node ) {
-	MUTATE_START( node );
-
-	node->condition = mutateExpression( node->condition );
-	maybeMutate_impl( node->message, *this );
-
-	MUTATE_END( StaticAssertDecl, node );
-}
-
-//--------------------------------------------------------------------------
-// InlineMemberDecl
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( InlineMemberDecl * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->type, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const InlineMemberDecl * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->type, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-DeclarationWithType * PassVisitor< pass_type >::mutate( InlineMemberDecl * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->type, *this );
-
-	MUTATE_END( DeclarationWithType, node );
-}
-
-//--------------------------------------------------------------------------
-// CompoundStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( CompoundStmt * node ) {
-	VISIT_START( node );
-	{
-		// Do not enter a new scope if atFunctionTop is true, don't leave one either.
-		ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
-		auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
-		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
-		atFunctionTop = false;
-		visitStatementList( node->kids );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const CompoundStmt * node ) {
-	VISIT_START( node );
-	{
-		// Do not enter a new scope if atFunctionTop is true, don't leave one either.
-		ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
-		auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
-		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
-		atFunctionTop = false;
-		visitStatementList( node->kids );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-CompoundStmt * PassVisitor< pass_type >::mutate( CompoundStmt * node ) {
-	MUTATE_START( node );
-	{
-		// Do not enter a new scope if atFunctionTop is true, don't leave one either.
-		ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
-		auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
-		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
-		atFunctionTop = false;
-		mutateStatementList( node->kids );
-	}
-	MUTATE_END( CompoundStmt, node );
-}
-
-//--------------------------------------------------------------------------
-// ExprStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ExprStmt * node ) {
-	VISIT_START( node );
-
-	visitExpression( node->expr );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ExprStmt * node ) {
-	VISIT_START( node );
-
-	visitExpression( node->expr );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( ExprStmt * node ) {
-	MUTATE_START( node );
-
-	node->expr = mutateExpression( node->expr );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// AsmStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( AsmStmt * node ) {
-	VISIT_START( node )
-
-	maybeAccept_impl( node->instruction, *this );
-	maybeAccept_impl( node->output, *this );
-	maybeAccept_impl( node->input, *this );
-	maybeAccept_impl( node->clobber, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const AsmStmt * node ) {
-	VISIT_START( node )
-
-	maybeAccept_impl( node->instruction, *this );
-	maybeAccept_impl( node->output, *this );
-	maybeAccept_impl( node->input, *this );
-	maybeAccept_impl( node->clobber, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( AsmStmt * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->instruction, *this );
-	maybeMutate_impl( node->output, *this );
-	maybeMutate_impl( node->input, *this );
-	maybeMutate_impl( node->clobber, *this );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// AsmStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( DirectiveStmt * node ) {
-	VISIT_START( node )
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const DirectiveStmt * node ) {
-	VISIT_START( node )
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( DirectiveStmt * node ) {
-	MUTATE_START( node );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// IfStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( IfStmt * node ) {
-	VISIT_START( node );
-	{
-		// if statements introduce a level of scope (for the initialization)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->initialization, *this );
-		visitExpression ( node->condition );
-		node->then = visitStatement( node->then );
-		node->else_ = visitStatement( node->else_ );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const IfStmt * node ) {
-	VISIT_START( node );
-	{
-		// if statements introduce a level of scope (for the initialization)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->initialization, *this );
-		visitExpression ( node->condition );
-		visitStatement  ( node->then );
-		visitStatement  ( node->else_ );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( IfStmt * node ) {
-	MUTATE_START( node );
-	{
-		// if statements introduce a level of scope (for the initialization)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->initialization, *this );
-		node->condition = mutateExpression( node->condition );
-		node->then  = mutateStatement ( node->then  );
-		node->else_  = mutateStatement ( node->else_  );
-	}
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// WhileDoStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( WhileDoStmt * node ) {
-	VISIT_START( node );
-
-	{
-		// while statements introduce a level of scope (for the initialization)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->initialization, *this );
-		visitExpression ( node->condition );
-		node->body = visitStatement( node->body );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const WhileDoStmt * node ) {
-	VISIT_START( node );
-
-	{
-		// while statements introduce a level of scope (for the initialization)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->initialization, *this );
-		visitExpression ( node->condition );
-		visitStatement  ( node->body );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( WhileDoStmt * node ) {
-	MUTATE_START( node );
-
-	{
-		// while statements introduce a level of scope (for the initialization)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->initialization, *this );
-		node->condition = mutateExpression( node->condition );
-		node->body      = mutateStatement ( node->body      );
-	}
-
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// ForStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ForStmt * node ) {
-	VISIT_START( node );
-	{
-		// for statements introduce a level of scope (for the initialization)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->initialization, *this );
-		visitExpression( node->condition );
-		visitExpression( node->increment );
-		node->body = visitStatement( node->body );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ForStmt * node ) {
-	VISIT_START( node );
-	{
-		// for statements introduce a level of scope (for the initialization)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->initialization, *this );
-		visitExpression( node->condition );
-		visitExpression( node->increment );
-		visitStatement ( node->body );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( ForStmt * node ) {
-	MUTATE_START( node );
-	{
-		// for statements introduce a level of scope (for the initialization)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->initialization, *this );
-		node->condition = mutateExpression( node->condition );
-		node->increment = mutateExpression( node->increment );
-		node->body      = mutateStatement ( node->body      );
-	}
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// SwitchStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( SwitchStmt * node ) {
-	VISIT_START( node );
-
-	visitExpression   ( node->condition  );
-	visitStatementList( node->statements );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const SwitchStmt * node ) {
-	VISIT_START( node );
-
-	visitExpression   ( node->condition  );
-	visitStatementList( node->statements );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( SwitchStmt * node ) {
-	MUTATE_START( node );
-
-	node->condition = mutateExpression( node->condition );
-	mutateStatementList( node->statements );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// CaseStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( CaseStmt * node ) {
-	VISIT_START( node );
-
-	visitExpression   ( node->condition );
-	visitStatementList( node->stmts     );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const CaseStmt * node ) {
-	VISIT_START( node );
-
-	visitExpression   ( node->condition );
-	visitStatementList( node->stmts     );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( CaseStmt * node ) {
-	MUTATE_START( node );
-
-	node->condition = mutateExpression( node->condition );
-	mutateStatementList( node->stmts );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// BranchStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( BranchStmt * node ) {
-	VISIT_START( node );
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const BranchStmt * node ) {
-	VISIT_START( node );
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( BranchStmt * node ) {
-	MUTATE_START( node );
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// ReturnStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ReturnStmt * node ) {
-	VISIT_START( node );
-
-	visitExpression( node->expr );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ReturnStmt * node ) {
-	VISIT_START( node );
-
-	visitExpression( node->expr );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( ReturnStmt * node ) {
-	MUTATE_START( node );
-
-	node->expr = mutateExpression( node->expr );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// ThrowStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ThrowStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->expr, *this );
-	maybeAccept_impl( node->target, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ThrowStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->expr, *this );
-	maybeAccept_impl( node->target, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( ThrowStmt * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->expr, *this );
-	maybeMutate_impl( node->target, *this );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// TryStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TryStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->block       , *this );
-	maybeAccept_impl( node->handlers    , *this );
-	maybeAccept_impl( node->finallyBlock, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TryStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->block       , *this );
-	maybeAccept_impl( node->handlers    , *this );
-	maybeAccept_impl( node->finallyBlock, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( TryStmt * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->block       , *this );
-	maybeMutate_impl( node->handlers    , *this );
-	maybeMutate_impl( node->finallyBlock, *this );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// CatchStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( CatchStmt * node ) {
-	VISIT_START( node );
-	{
-		// catch statements introduce a level of scope (for the caught exception)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->decl, *this );
-		node->cond = visitExpression( node->cond );
-		node->body = visitStatement ( node->body );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const CatchStmt * node ) {
-	VISIT_START( node );
-	{
-		// catch statements introduce a level of scope (for the caught exception)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->decl, *this );
-		visitExpression ( node->cond );
-		visitStatement  ( node->body );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( CatchStmt * node ) {
-	MUTATE_START( node );
-	{
-		// catch statements introduce a level of scope (for the caught exception)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->decl, *this );
-		node->cond = mutateExpression( node->cond );
-		node->body = mutateStatement ( node->body );
-	}
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// FinallyStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( FinallyStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->block, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const FinallyStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->block, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( FinallyStmt * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->block, *this );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// SuspendStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( SuspendStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->then  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const SuspendStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->then  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( SuspendStmt * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->then  , *this );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// WaitForStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( WaitForStmt * node ) {
-	VISIT_START( node );
-
-	for( auto & clause : node->clauses ) {
-		maybeAccept_impl( clause.target.function, *this );
-		maybeAccept_impl( clause.target.arguments, *this );
-
-		maybeAccept_impl( clause.statement, *this );
-		maybeAccept_impl( clause.condition, *this );
-	}
-
-	maybeAccept_impl( node->timeout.time, *this );
-	maybeAccept_impl( node->timeout.statement, *this );
-	maybeAccept_impl( node->timeout.condition, *this );
-	maybeAccept_impl( node->orelse.statement, *this );
-	maybeAccept_impl( node->orelse.condition, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const WaitForStmt * node ) {
-	VISIT_START( node );
-
-	for( auto & clause : node->clauses ) {
-		maybeAccept_impl( clause.target.function, *this );
-		maybeAccept_impl( clause.target.arguments, *this );
-
-		maybeAccept_impl( clause.statement, *this );
-		maybeAccept_impl( clause.condition, *this );
-	}
-
-	maybeAccept_impl( node->timeout.time, *this );
-	maybeAccept_impl( node->timeout.statement, *this );
-	maybeAccept_impl( node->timeout.condition, *this );
-	maybeAccept_impl( node->orelse.statement, *this );
-	maybeAccept_impl( node->orelse.condition, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( WaitForStmt * node ) {
-	MUTATE_START( node );
-
-	for( auto & clause : node->clauses ) {
-		maybeMutate_impl( clause.target.function, *this );
-		maybeMutate_impl( clause.target.arguments, *this );
-
-		maybeMutate_impl( clause.statement, *this );
-		maybeMutate_impl( clause.condition, *this );
-	}
-
-	maybeMutate_impl( node->timeout.time, *this );
-	maybeMutate_impl( node->timeout.statement, *this );
-	maybeMutate_impl( node->timeout.condition, *this );
-	maybeMutate_impl( node->orelse.statement, *this );
-	maybeMutate_impl( node->orelse.condition, *this );
-
-	MUTATE_END( Statement, node );
-}
-
-
-
-//--------------------------------------------------------------------------
-// WithStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( WithStmt * node ) {
-	VISIT_START( node );
-	maybeAccept_impl( node->exprs, *this );
-	{
-		// catch statements introduce a level of scope (for the caught exception)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		indexerAddWith( node->exprs, node );
-		maybeAccept_impl( node->stmt, *this );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const WithStmt * node ) {
-	VISIT_START( node );
-	maybeAccept_impl( node->exprs, *this );
-	{
-		// catch statements introduce a level of scope (for the caught exception)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		indexerAddWith( node->exprs, node );
-		maybeAccept_impl( node->stmt, *this );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( WithStmt * node ) {
-	MUTATE_START( node );
-	maybeMutate_impl( node->exprs, *this );
-	{
-		// catch statements introduce a level of scope (for the caught exception)
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		indexerAddWith( node->exprs, node );
-		maybeMutate_impl( node->stmt, *this );
-	}
-	MUTATE_END( Declaration, node );
-}
-
-//--------------------------------------------------------------------------
-// NullStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( NullStmt * node ) {
-	VISIT_START( node );
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const NullStmt * node ) {
-	VISIT_START( node );
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-NullStmt * PassVisitor< pass_type >::mutate( NullStmt * node ) {
-	MUTATE_START( node );
-	MUTATE_END( NullStmt, node );
-}
-
-//--------------------------------------------------------------------------
-// DeclStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( DeclStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->decl, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const DeclStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->decl, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( DeclStmt * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->decl, *this );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// ImplicitCtorDtorStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ImplicitCtorDtorStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->callStmt, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ImplicitCtorDtorStmt * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->callStmt, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( ImplicitCtorDtorStmt * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->callStmt, *this );
-
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// MutexStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( MutexStmt * node ) {
-	VISIT_START( node );
-	// mutex statements introduce a level of scope (for the initialization)
-	maybeAccept_impl( node->mutexObjs, *this );
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		node->stmt = visitStatement( node->stmt );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const MutexStmt * node ) {
-	VISIT_START( node );
-	maybeAccept_impl( node->mutexObjs, *this );
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		visitStatement( node->stmt );
-	}
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( MutexStmt * node ) {
-	MUTATE_START( node );
-	maybeMutate_impl( node->mutexObjs, *this );
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		node->stmt = mutateStatement( node->stmt );
-	}
-	MUTATE_END( Statement, node );
-}
-
-//--------------------------------------------------------------------------
-// ApplicationExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ApplicationExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result  , *this );
-	maybeAccept_impl   ( node->function, *this );
-	maybeAccept_impl   ( node->args    , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ApplicationExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result  , *this );
-	maybeAccept_impl   ( node->function, *this );
-	maybeAccept_impl   ( node->args    , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( ApplicationExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env     , *this );
-	indexerScopedMutate( node->result  , *this );
-	maybeMutate_impl   ( node->function, *this );
-	maybeMutate_impl   ( node->args    , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// UntypedExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( UntypedExpr * node ) {
-	VISIT_START( node );
-
-	// maybeAccept_impl( node->get_env(), *this );
-	indexerScopedAccept( node->result, *this );
-
-	for ( auto expr : node->args ) {
-		visitExpression( expr );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const UntypedExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-
-	for ( auto expr : node->args ) {
-		visitExpression( expr );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( UntypedExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-
-	for ( auto& expr : node->args ) {
-		expr = mutateExpression( expr );
-	}
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// NameExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( NameExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const NameExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( NameExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// QualifiedNameExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( QualifiedNameExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl( node->type_decl, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const QualifiedNameExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl( node->type_decl, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( QualifiedNameExpr * node ) {
-	MUTATE_START( node );
-
-    indexerScopedMutate( node->env   , *this );
-    indexerScopedMutate( node->result, *this );
-	maybeMutate_impl( node->type_decl, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// CastExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( CastExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg   , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const CastExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg   , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( CastExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->arg   , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// KeywordCastExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( KeywordCastExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl        ( node->arg   , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const KeywordCastExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg   , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( KeywordCastExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->arg   , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// VirtualCastExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( VirtualCastExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const VirtualCastExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( VirtualCastExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->arg   , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// AddressExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( AddressExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg   , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const AddressExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg   , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( AddressExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->arg   , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// LabelAddressExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( LabelAddressExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const LabelAddressExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( LabelAddressExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// UntypedMemberExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( UntypedMemberExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result   , *this );
-	maybeAccept_impl   ( node->aggregate, *this );
-	maybeAccept_impl   ( node->member   , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const UntypedMemberExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result   , *this );
-	maybeAccept_impl   ( node->aggregate, *this );
-	maybeAccept_impl   ( node->member   , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( UntypedMemberExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env      , *this );
-	indexerScopedMutate( node->result   , *this );
-	maybeMutate_impl   ( node->aggregate, *this );
-	maybeMutate_impl   ( node->member   , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// MemberExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( MemberExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result   , *this );
-	maybeAccept_impl   ( node->aggregate, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const MemberExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result   , *this );
-	maybeAccept_impl   ( node->aggregate, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( MemberExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env      , *this );
-	indexerScopedMutate( node->result   , *this );
-	maybeMutate_impl   ( node->aggregate, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// VariableExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( VariableExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const VariableExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( VariableExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// ConstantExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ConstantExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result   , *this );
-	maybeAccept_impl   ( &node->constant, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ConstantExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result   , *this );
-	maybeAccept_impl   ( &node->constant, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( ConstantExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	Constant * ptr = &node->constant;
-	maybeMutate_impl( ptr, *this );
-	node->constant = *ptr;
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// SizeofExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( SizeofExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	if ( node->get_isType() ) {
-		maybeAccept_impl( node->type, *this );
-	} else {
-		maybeAccept_impl( node->expr, *this );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const SizeofExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	if ( node->get_isType() ) {
-		maybeAccept_impl( node->type, *this );
-	} else {
-		maybeAccept_impl( node->expr, *this );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( SizeofExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	if ( node->get_isType() ) {
-		maybeMutate_impl( node->type, *this );
-	} else {
-		maybeMutate_impl( node->expr, *this );
-	}
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// AlignofExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( AlignofExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	if ( node->get_isType() ) {
-		maybeAccept_impl( node->type, *this );
-	} else {
-		maybeAccept_impl( node->expr, *this );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const AlignofExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	if ( node->get_isType() ) {
-		maybeAccept_impl( node->type, *this );
-	} else {
-		maybeAccept_impl( node->expr, *this );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( AlignofExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	if ( node->get_isType() ) {
-		maybeMutate_impl( node->type, *this );
-	} else {
-		maybeMutate_impl( node->expr, *this );
-	}
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// UntypedOffsetofExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( UntypedOffsetofExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->type  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const UntypedOffsetofExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->type  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( UntypedOffsetofExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->type  , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// OffsetofExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( OffsetofExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->type  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const OffsetofExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->type  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( OffsetofExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->type  , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// OffsetPackExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( OffsetPackExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->type  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const OffsetPackExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->type  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( OffsetPackExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->type  , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// LogicalExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( LogicalExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg1  , *this );
-	maybeAccept_impl   ( node->arg2  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const LogicalExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg1  , *this );
-	maybeAccept_impl   ( node->arg2  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( LogicalExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->arg1  , *this );
-	maybeMutate_impl   ( node->arg2  , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// ConditionalExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ConditionalExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl        ( node->arg1  , *this );
-	maybeAccept_impl        ( node->arg2  , *this );
-	maybeAccept_impl        ( node->arg3  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ConditionalExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg1  , *this );
-	maybeAccept_impl   ( node->arg2  , *this );
-	maybeAccept_impl   ( node->arg3  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( ConditionalExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->arg1  , *this );
-	maybeMutate_impl   ( node->arg2  , *this );
-	maybeMutate_impl   ( node->arg3  , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// CommaExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( CommaExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg1  , *this );
-	maybeAccept_impl   ( node->arg2  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const CommaExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->arg1  , *this );
-	maybeAccept_impl   ( node->arg2  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( CommaExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->arg1  , *this );
-	maybeMutate_impl   ( node->arg2  , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// TypeExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TypeExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->type, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TypeExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->type, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( TypeExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->type  , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// DimensionExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( DimensionExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const DimensionExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( DimensionExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// AsmExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( AsmExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result    , *this );
-	maybeAccept_impl   ( node->constraint, *this );
-	maybeAccept_impl   ( node->operand   , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const AsmExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result    , *this );
-	maybeAccept_impl   ( node->constraint, *this );
-	maybeAccept_impl   ( node->operand   , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( AsmExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env       , *this );
-	indexerScopedMutate( node->result    , *this );
-	maybeMutate_impl   ( node->constraint, *this );
-	maybeMutate_impl   ( node->operand   , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// ImplicitCopyCtorExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ImplicitCopyCtorExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result    , *this );
-	maybeAccept_impl   ( node->callExpr  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ImplicitCopyCtorExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result    , *this );
-	maybeAccept_impl   ( node->callExpr  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( ImplicitCopyCtorExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env       , *this );
-	indexerScopedMutate( node->result    , *this );
-	maybeMutate_impl   ( node->callExpr  , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// ConstructorExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ConstructorExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result  , *this );
-	maybeAccept_impl   ( node->callExpr, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ConstructorExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result  , *this );
-	maybeAccept_impl   ( node->callExpr, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( ConstructorExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env     , *this );
-	indexerScopedMutate( node->result  , *this );
-	maybeMutate_impl   ( node->callExpr, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// CompoundLiteralExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( CompoundLiteralExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result     , *this );
-	maybeAccept_impl   ( node->initializer, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const CompoundLiteralExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result     , *this );
-	maybeAccept_impl   ( node->initializer, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( CompoundLiteralExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env        , *this );
-	indexerScopedMutate( node->result     , *this );
-	maybeMutate_impl     ( node->initializer, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// RangeExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( RangeExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->low   , *this );
-	maybeAccept_impl   ( node->high  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const RangeExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->low   , *this );
-	maybeAccept_impl   ( node->high  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( RangeExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->low   , *this );
-	maybeMutate_impl   ( node->high  , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// UntypedTupleExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( UntypedTupleExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->exprs , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const UntypedTupleExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->exprs , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( UntypedTupleExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->exprs , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// TupleExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TupleExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->exprs , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TupleExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->exprs , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( TupleExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->exprs , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// TupleIndexExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TupleIndexExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->tuple , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TupleIndexExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->tuple , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( TupleIndexExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->tuple , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// TupleAssignExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TupleAssignExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result  , *this );
-	maybeAccept_impl   ( node->stmtExpr, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TupleAssignExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result  , *this );
-	maybeAccept_impl( node->stmtExpr, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( TupleAssignExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env     , *this );
-	indexerScopedMutate( node->result  , *this );
-	maybeMutate_impl   ( node->stmtExpr, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// StmtExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( StmtExpr * node ) {
-	VISIT_START( node );
-
-	// don't want statements from outer CompoundStmts to be added to this StmtExpr
-	ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
-	ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
-	ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
-
-	indexerScopedAccept( node->result     , *this );
-	maybeAccept_impl   ( node->statements , *this );
-	maybeAccept_impl   ( node->returnDecls, *this );
-	maybeAccept_impl   ( node->dtors      , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const StmtExpr * node ) {
-	VISIT_START( node );
-
-	// don't want statements from outer CompoundStmts to be added to this StmtExpr
-	ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
-	ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
-	ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
-
-	indexerScopedAccept( node->result     , *this );
-	maybeAccept_impl   ( node->statements , *this );
-	maybeAccept_impl   ( node->returnDecls, *this );
-	maybeAccept_impl   ( node->dtors      , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( StmtExpr * node ) {
-	MUTATE_START( node );
-
-	// don't want statements from outer CompoundStmts to be added to this StmtExpr
-	ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
-	ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
-	ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
-
-	indexerScopedMutate( node->result     , *this );
-	maybeMutate_impl   ( node->statements , *this );
-	maybeMutate_impl   ( node->returnDecls, *this );
-	maybeMutate_impl   ( node->dtors      , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// UniqueExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( UniqueExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->expr  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const UniqueExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->expr  , *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( UniqueExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->expr  , *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// UntypedInitExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( UntypedInitExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->expr  , *this );
-	// not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const UntypedInitExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->expr  , *this );
-	// not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( UntypedInitExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->expr  , *this );
-	// not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// InitExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( InitExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->expr  , *this );
-	maybeAccept_impl   ( node->designation, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const InitExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->expr  , *this );
-	maybeAccept_impl   ( node->designation, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( InitExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env   , *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl   ( node->expr  , *this );
-	maybeMutate_impl   ( node->designation, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// DeletedExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( DeletedExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->expr, *this );
-	// don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const DeletedExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->expr, *this );
-	// don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( DeletedExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env, *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl( node->expr, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// DefaultArgExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( DefaultArgExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->expr, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const DefaultArgExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl   ( node->expr, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( DefaultArgExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env, *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl( node->expr, *this );
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// GenericExpr
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( GenericExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl( node->control, *this );
-	for ( GenericExpr::Association & assoc : node->associations ) {
-		indexerScopedAccept( assoc.type, *this );
-		maybeAccept_impl( assoc.expr, *this );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const GenericExpr * node ) {
-	VISIT_START( node );
-
-	indexerScopedAccept( node->result, *this );
-	maybeAccept_impl( node->control, *this );
-	for ( const GenericExpr::Association & assoc : node->associations ) {
-		indexerScopedAccept( assoc.type, *this );
-		maybeAccept_impl( assoc.expr, *this );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( GenericExpr * node ) {
-	MUTATE_START( node );
-
-	indexerScopedMutate( node->env, *this );
-	indexerScopedMutate( node->result, *this );
-	maybeMutate_impl( node->control, *this );
-	for ( GenericExpr::Association & assoc : node->associations ) {
-		indexerScopedMutate( assoc.type, *this );
-		maybeMutate_impl( assoc.expr, *this );
-	}
-
-	MUTATE_END( Expression, node );
-}
-
-//--------------------------------------------------------------------------
-// VoidType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( VoidType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const VoidType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( VoidType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// BasicType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( BasicType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const BasicType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( BasicType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// PointerType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( PointerType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->dimension, *this );
-	maybeAccept_impl( node->base, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const PointerType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->dimension, *this );
-	maybeAccept_impl( node->base, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( PointerType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-	maybeMutate_impl( node->dimension, *this );
-	maybeMutate_impl( node->base, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// ArrayType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ArrayType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->dimension, *this );
-	maybeAccept_impl( node->base, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ArrayType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->dimension, *this );
-	maybeAccept_impl( node->base, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( ArrayType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-	maybeMutate_impl( node->dimension, *this );
-	maybeMutate_impl( node->base, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// ReferenceType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ReferenceType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->base, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ReferenceType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->base, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( ReferenceType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-	maybeMutate_impl( node->base, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// QualifiedType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( QualifiedType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->parent, *this );
-	maybeAccept_impl( node->child, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const QualifiedType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->parent, *this );
-	maybeAccept_impl( node->child, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( QualifiedType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-	maybeMutate_impl( node->parent, *this );
-	maybeMutate_impl( node->child, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// FunctionType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( FunctionType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->returnVals, *this );
-	maybeAccept_impl( node->parameters, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const FunctionType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->returnVals, *this );
-	maybeAccept_impl( node->parameters, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( FunctionType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-	maybeMutate_impl( node->returnVals, *this );
-	maybeMutate_impl( node->parameters, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// StructInstType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( StructInstType * node ) {
-	VISIT_START( node );
-
-	indexerAddStruct( node->name );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->forall    , *this );
-		maybeAccept_impl( node->parameters, *this );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const StructInstType * node ) {
-	VISIT_START( node );
-
-	indexerAddStruct( node->name );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->forall    , *this );
-		maybeAccept_impl( node->parameters, *this );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( StructInstType * node ) {
-	MUTATE_START( node );
-
-	indexerAddStruct( node->name );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->forall    , *this );
-		maybeMutate_impl( node->parameters, *this );
-	}
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// UnionInstType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( UnionInstType * node ) {
-	VISIT_START( node );
-
-	indexerAddUnion( node->name );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->forall    , *this );
-		maybeAccept_impl( node->parameters, *this );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const UnionInstType * node ) {
-	VISIT_START( node );
-
-	indexerAddUnion( node->name );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->forall    , *this );
-		maybeAccept_impl( node->parameters, *this );
-	}
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( UnionInstType * node ) {
-	MUTATE_START( node );
-
-	indexerAddUnion( node->name );
-
-	{
-		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->forall    , *this );
-		maybeMutate_impl( node->parameters, *this );
-	}
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// EnumInstType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( EnumInstType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->parameters, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const EnumInstType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->parameters, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( EnumInstType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-	maybeMutate_impl( node->parameters, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// TraitInstType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TraitInstType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall    , *this );
-	maybeAccept_impl( node->parameters, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TraitInstType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall    , *this );
-	maybeAccept_impl( node->parameters, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( TraitInstType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall    , *this );
-	maybeMutate_impl( node->parameters, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// TypeInstType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TypeInstType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall    , *this );
-	maybeAccept_impl( node->parameters, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TypeInstType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall    , *this );
-	maybeAccept_impl( node->parameters, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( TypeInstType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall    , *this );
-	maybeMutate_impl( node->parameters, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// TupleType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TupleType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->types, *this );
-	maybeAccept_impl( node->members, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TupleType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->types, *this );
-	maybeAccept_impl( node->members, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( TupleType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-	maybeMutate_impl( node->types, *this );
-	maybeMutate_impl( node->members, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// TypeofType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( TypeofType * node ) {
-	VISIT_START( node );
-
-	assert( node->expr );
-	maybeAccept_impl( node->expr, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const TypeofType * node ) {
-	VISIT_START( node );
-
-	assert( node->expr );
-	maybeAccept_impl( node->expr, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( TypeofType * node ) {
-	MUTATE_START( node );
-
-	assert( node->expr );
-	maybeMutate_impl( node->expr, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// VTableType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( VTableType * node ) {
-	VISIT_START( node );
-
-	// Forall qualifiers should be on base type, not here
-	// maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->base, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const VTableType * node ) {
-	VISIT_START( node );
-
-	// Forall qualifiers should be on base type, not here
-	// maybeAccept_impl( node->forall, *this );
-	maybeAccept_impl( node->base, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( VTableType * node ) {
-	MUTATE_START( node );
-
-	// Forall qualifiers should be on base type, not here
-	// maybeMutate_impl( node->forall, *this );
-	maybeMutate_impl( node->base, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// AttrType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( AttrType * node ) {
-	VISIT_START( node );
-
-	if ( node->isType ) {
-		assert( node->type );
-		maybeAccept_impl( node->type, *this );
-	} else {
-		assert( node->expr );
-		maybeAccept_impl( node->expr, *this );
-	} // if
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const AttrType * node ) {
-	VISIT_START( node );
-
-	if ( node->isType ) {
-		assert( node->type );
-		maybeAccept_impl( node->type, *this );
-	} else {
-		assert( node->expr );
-		maybeAccept_impl( node->expr, *this );
-	} // if
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( AttrType * node ) {
-	MUTATE_START( node );
-
-	if ( node->isType ) {
-		assert( node->type );
-		maybeMutate_impl( node->type, *this );
-	} else {
-		assert( node->expr );
-		maybeMutate_impl( node->expr, *this );
-	} // if
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// VarArgsType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( VarArgsType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const VarArgsType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// ZeroType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ZeroType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ZeroType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( ZeroType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// OneType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( OneType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const OneType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( OneType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// GlobalScopeType
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( GlobalScopeType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const GlobalScopeType * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->forall, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( GlobalScopeType * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->forall, *this );
-
-	MUTATE_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
-// Designation
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( Designation * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->designators, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const Designation * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->designators, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Designation * PassVisitor< pass_type >::mutate( Designation * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->designators, *this );
-
-	MUTATE_END( Designation, node );
-}
-
-//--------------------------------------------------------------------------
-// SingleInit
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( SingleInit * node ) {
-	VISIT_START( node );
-
-	visitExpression( node->value );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const SingleInit * node ) {
-	VISIT_START( node );
-
-	visitExpression( node->value );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Initializer * PassVisitor< pass_type >::mutate( SingleInit * node ) {
-	MUTATE_START( node );
-
-	node->value = mutateExpression( node->value );
-
-	MUTATE_END( Initializer, node );
-}
-
-//--------------------------------------------------------------------------
-// ListInit
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ListInit * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->designations, *this );
-	maybeAccept_impl( node->initializers, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ListInit * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->designations, *this );
-	maybeAccept_impl( node->initializers, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Initializer * PassVisitor< pass_type >::mutate( ListInit * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->designations, *this );
-	maybeMutate_impl( node->initializers, *this );
-
-	MUTATE_END( Initializer, node );
-}
-
-//--------------------------------------------------------------------------
-// ConstructorInit
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( ConstructorInit * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->ctor, *this );
-	maybeAccept_impl( node->dtor, *this );
-	maybeAccept_impl( node->init, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const ConstructorInit * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->ctor, *this );
-	maybeAccept_impl( node->dtor, *this );
-	maybeAccept_impl( node->init, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Initializer * PassVisitor< pass_type >::mutate( ConstructorInit * node ) {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->ctor, *this );
-	maybeMutate_impl( node->dtor, *this );
-	maybeMutate_impl( node->init, *this );
-
-	MUTATE_END( Initializer, node );
-}
-
-//--------------------------------------------------------------------------
-// Constant
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( Constant * node ) {
-	VISIT_START( node );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const Constant * node ) {
-	VISIT_START( node );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Constant * PassVisitor< pass_type >::mutate( Constant * node  )  {
-	MUTATE_START( node );
-
-	MUTATE_END( Constant, node );
-}
-
-//--------------------------------------------------------------------------
-// Attribute
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( Attribute * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->parameters, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( const Attribute * node ) {
-	VISIT_START( node );
-
-	maybeAccept_impl( node->parameters, *this );
-
-	VISIT_END( node );
-}
-
-template< typename pass_type >
-Attribute * PassVisitor< pass_type >::mutate( Attribute * node  )  {
-	MUTATE_START( node );
-
-	maybeMutate_impl( node->parameters, *this );
-
-	MUTATE_END( Attribute, node );
-}
-
-//--------------------------------------------------------------------------
-// TypeSubstitution
-template< typename pass_type >
-TypeSubstitution * PassVisitor< pass_type >::mutate( TypeSubstitution * node ) {
-	MUTATE_START( node );
-
-	for ( auto & p : node->typeEnv ) {
-		indexerScopedMutate( p.second, *this );
-	}
-	for ( auto & p : node->varEnv ) {
-		indexerScopedMutate( p.second, *this );
-	}
-
-	MUTATE_END( TypeSubstitution, node );
-}
-
-#undef VISIT_START
-#undef VISIT_END
-
-#undef MUTATE_START
-#undef MUTATE_END
Index: c/Common/PassVisitor.proto.h
===================================================================
--- src/Common/PassVisitor.proto.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,280 +1,0 @@
-#pragma once
-// IWYU pragma: private, include "PassVisitor.h"
-
-template<typename pass_type>
-class PassVisitor;
-
-typedef std::function<void( void * )> cleanup_func_t;
-typedef std::function< void( cleanup_func_t, void * ) > at_cleanup_t;
-
-class guard_value_impl {
-public:
-	guard_value_impl( at_cleanup_t * at_cleanup ) {
-		if( at_cleanup ) {
-			*at_cleanup = [this]( cleanup_func_t && func, void* val ) {
-				push( std::move( func ), val );
-			};
-		}
-	}
-
-	~guard_value_impl() {
-		while( !cleanups.empty() ) {
-			auto& cleanup = cleanups.top();
-			cleanup.func( cleanup.val );
-			cleanups.pop();
-		}
-	}
-
-	void push( cleanup_func_t && func, void* val ) {
-		cleanups.emplace( std::move(func), val );
-	}
-
-private:
-	struct cleanup_t {
-		cleanup_func_t func;
-		void * val;
-
-		cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {}
-	};
-
-	std::stack< cleanup_t, std::vector< cleanup_t > > cleanups;
-};
-
-class bool_ref {
-public:
-	bool_ref() = default;
-	~bool_ref() = default;
-
-	operator bool() { return m_ref ? *m_ref : true; }
-	bool operator=( bool val ) { assert(m_ref); return *m_ref = val; }
-
-private:
-
-	friend class ChildrenGuard;
-
-	bool * set( bool * val ) {
-		bool * prev = m_ref;
-		m_ref = val;
-		return prev;
-	}
-
-	bool * m_ref = nullptr;
-};
-
-class ChildrenGuard {
-public:
-
-	ChildrenGuard( bool_ref * ref )
-		: m_val ( true )
-		, m_prev( ref ? ref->set( &m_val ) : nullptr )
-		, m_ref ( ref )
-	{}
-
-	~ChildrenGuard() {
-		if( m_ref ) {
-			m_ref->set( m_prev );
-		}
-	}
-
-	operator bool() { return m_val; }
-
-private:
-	bool       m_val;
-	bool     * m_prev;
-	bool_ref * m_ref;
-};
-
-//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-// Deep magic (a.k.a template meta programming) to make the templated visitor work
-// Basically the goal is to make 2 previsit_impl
-// 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of
-//     'pass.previsit( node )' that compiles will be used for that node for that type
-//     This requires that this option only compile for passes that actually define an appropriate visit.
-//     SFINAE will make sure the compilation errors in this function don't halt the build.
-//     See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE
-// 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing.
-//     This is needed only to eliminate the need for passes to specify any kind of handlers.
-//     The second implementation only works because it has a lower priority. This is due to the bogus last parameter.
-//     The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0
-//     the first implementation takes priority in regards to overloading.
-// Mutator functions work along the same principal
-//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-// Visit
-template<typename pass_type, typename node_type>
-static inline auto previsit_impl( pass_type& pass, node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.previsit( node ), void() ) {
-	pass.previsit( node );
-}
-
-template<typename pass_type, typename node_type>
-static inline void previsit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) node_type * node, __attribute__((unused)) long unused ) {}
-
-
-template<typename pass_type, typename node_type>
-static inline auto postvisit_impl( pass_type& pass, node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.postvisit( node ), void() ) {
-	pass.postvisit( node );
-}
-
-template<typename pass_type, typename node_type>
-static inline void postvisit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) node_type * node, __attribute__((unused)) long unused ) {}
-
-template<typename pass_type, typename node_type>
-static inline auto previsit_impl( pass_type& pass, const node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.previsit( node ), void() ) {
-	pass.previsit( node );
-}
-
-template<typename pass_type, typename node_type>
-static inline void previsit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) const node_type * node, __attribute__((unused)) long unused ) {}
-
-
-template<typename pass_type, typename node_type>
-static inline auto postvisit_impl( pass_type& pass, const node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.postvisit( node ), void() ) {
-	pass.postvisit( node );
-}
-
-template<typename pass_type, typename node_type>
-static inline void postvisit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) const node_type * node, __attribute__((unused)) long unused ) {}
-
-//---------------------------------------------------------
-// Mutate
-template<typename pass_type, typename node_type>
-static inline auto premutate_impl( pass_type& pass, node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.premutate( node ), void() ) {
-	return pass.premutate( node );
-}
-
-template<typename pass_type, typename node_type>
-static inline void premutate_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) node_type * node, __attribute__((unused)) long unused ) {}
-
-
-template<typename return_type, typename pass_type, typename node_type>
-static inline auto postmutate_impl( pass_type& pass, node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.postmutate( node ) ) {
-	return pass.postmutate( node );
-}
-
-template<typename return_type, typename pass_type, typename node_type>
-static inline return_type postmutate_impl( __attribute__((unused)) pass_type& pass, node_type * node, __attribute__((unused)) long unused ) { return node; }
-
-//---------------------------------------------------------
-// Begin/End scope
-template<typename pass_type>
-static inline auto begin_scope_impl( pass_type& pass, __attribute__((unused)) int unused ) -> decltype( pass.beginScope(), void() ) {
-	pass.beginScope();
-}
-
-template<typename pass_type>
-static inline void begin_scope_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) {}
-
-
-template<typename pass_type>
-static inline auto end_scope_impl( pass_type& pass, __attribute__((unused)) int unused ) -> decltype( pass.endScope(), void() ) {
-	pass.endScope();
-}
-
-template<typename pass_type>
-static inline void end_scope_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) {}
-
-//---------------------------------------------------------
-// Fields
-#define FIELD_PTR( type, name )                                                                                                        \
-template<typename pass_type>                                                                                                           \
-static inline auto name##_impl( pass_type& pass, __attribute__((unused)) int unused ) -> decltype( &pass.name ) { return &pass.name; } \
-                                                                                                                                       \
-template<typename pass_type>                                                                                                           \
-static inline type * name##_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) { return nullptr;}    \
-
-FIELD_PTR( const TypeSubstitution *, env )
-FIELD_PTR( std::list< Statement* >, stmtsToAddBefore )
-FIELD_PTR( std::list< Statement* >, stmtsToAddAfter  )
-FIELD_PTR( std::list< Declaration* >, declsToAddBefore )
-FIELD_PTR( std::list< Declaration* >, declsToAddAfter  )
-FIELD_PTR( bool_ref, visit_children )
-FIELD_PTR( at_cleanup_t, at_cleanup )
-FIELD_PTR( PassVisitor<pass_type> * const, visitor )
-
-#undef FIELD_PTR
-
-//---------------------------------------------------------
-// Indexer
-template<typename pass_type>
-static inline auto indexer_impl_enterScope( pass_type & pass, int ) -> decltype( pass.indexer.enterScope(), void() ) {
-	pass.indexer.enterScope();
-}
-
-template<typename pass_type>
-static inline auto indexer_impl_enterScope( pass_type &, long ) {}
-
-template<typename pass_type>
-static inline auto indexer_impl_leaveScope( pass_type & pass, int ) -> decltype( pass.indexer.leaveScope(), void() ) {
-	pass.indexer.leaveScope();
-}
-
-template<typename pass_type>
-static inline auto indexer_impl_leaveScope( pass_type &, long ) {}
-
-
-#define INDEXER_FUNC1( func, type )                                                                                             \
-template<typename pass_type>                                                                                                   \
-static inline auto indexer_impl_##func ( pass_type & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {   \
-	pass.indexer.func( arg );                                                                                                \
-}                                                                                                                              \
-template<typename pass_type>                                                                                                   \
-static inline void indexer_impl_##func ( pass_type &, long, type ) { }
-
-#define INDEXER_FUNC2( func, type1, type2 )                                                                                             \
-template<typename pass_type>                                                                                                   \
-static inline auto indexer_impl_##func ( pass_type & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.indexer.func( arg1, arg2 ), void() ) {   \
-	pass.indexer.func( arg1, arg2 );                                                                                                \
-}                                                                                                                              \
-template<typename pass_type>                                                                                                   \
-static inline void indexer_impl_##func ( pass_type &, long, type1, type2 ) { }
-
-
-INDEXER_FUNC1( addId     , const DeclarationWithType *       );
-INDEXER_FUNC1( addType   , const NamedTypeDecl *             );
-INDEXER_FUNC1( addStruct , const StructDecl *                );
-INDEXER_FUNC1( addEnum   , const EnumDecl *                  );
-INDEXER_FUNC1( addUnion  , const UnionDecl *                 );
-INDEXER_FUNC1( addTrait  , const TraitDecl *                 );
-INDEXER_FUNC2( addWith   , const std::list< Expression * > &, const Declaration * );
-
-#undef INDEXER_FUNC1
-#undef INDEXER_FUNC2
-
-template<typename pass_type>
-static inline auto indexer_impl_addStructFwd( pass_type & pass, int, const StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
-	StructDecl * fwd = new StructDecl( decl->name );
-	cloneAll( decl->parameters, fwd->parameters );
-	pass.indexer.addStruct( fwd );
-}
-
-template<typename pass_type>
-static inline auto indexer_impl_addStructFwd( pass_type &, long, const StructDecl * ) {}
-
-template<typename pass_type>
-static inline auto indexer_impl_addUnionFwd( pass_type & pass, int, const UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
-	UnionDecl * fwd = new UnionDecl( decl->name );
-	cloneAll( decl->parameters, fwd->parameters );
-	pass.indexer.addUnion( fwd );
-}
-
-template<typename pass_type>
-static inline auto indexer_impl_addUnionFwd( pass_type &, long, const UnionDecl * ) {}
-
-template<typename pass_type>
-static inline auto indexer_impl_addStruct( pass_type & pass, int, const std::string & str ) -> decltype( pass.indexer.addStruct( str ), void() ) {
-	if ( ! pass.indexer.lookupStruct( str ) ) {
-		pass.indexer.addStruct( str );
-	}
-}
-
-template<typename pass_type>
-static inline auto indexer_impl_addStruct( pass_type &, long, const std::string & ) {}
-
-template<typename pass_type>
-static inline auto indexer_impl_addUnion( pass_type & pass, int, const std::string & str ) -> decltype( pass.indexer.addUnion( str ), void() ) {
-	if ( ! pass.indexer.lookupUnion( str ) ) {
-		pass.indexer.addUnion( str );
-	}
-}
-
-template<typename pass_type>
-static inline auto indexer_impl_addUnion( pass_type &, long, const std::string & ) {}
Index: src/Common/UniqueName.cc
===================================================================
--- src/Common/UniqueName.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Common/UniqueName.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -5,17 +5,16 @@
 // file "LICENCE" distributed with Cforall.
 //
-// UniqueName.cc -- 
+// UniqueName.cc -- Create a unique variants of a base name with a counter.
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jun  8 14:47:49 2015
-// Update Count     : 3
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Nov  7 15:04:00 2023
+// Update Count     : 4
 //
 
-#include <string>
-#include <sstream>
+#include "UniqueName.h"
 
-#include "UniqueName.h"
+#include "Common/ToString.hpp"
 
 UniqueName::UniqueName( const std::string &base ) : base( base ), count( 0 ) {
@@ -23,7 +22,5 @@
 
 std::string UniqueName::newName( const std::string &additional ) {
-	std::ostringstream os;
-	os << base << additional << count++;
-	return os.str();
+	return toString( base, additional, count++ );
 }
 
Index: src/Common/UniqueName.h
===================================================================
--- src/Common/UniqueName.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Common/UniqueName.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// UniqueName.h -- 
+// UniqueName.h -- Create a unique variants of a base name with a counter.
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul 21 22:18:45 2017
-// Update Count     : 2
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Nov  7 15:00:00 2023
+// Update Count     : 3
 //
 
@@ -19,8 +19,8 @@
 
 class UniqueName {
-  public:
-	UniqueName( const std::string &base = "" );
+public:
+	UniqueName( const std::string &base );
 	std::string newName( const std::string &additional = "" );
-  private:
+private:
 	std::string base;
 	int count;
Index: src/Common/module.mk
===================================================================
--- src/Common/module.mk	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Common/module.mk	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -31,8 +31,4 @@
 	Common/Indenter.cc \
 	Common/Iterate.hpp \
-	Common/PassVisitor.cc \
-	Common/PassVisitor.h \
-	Common/PassVisitor.impl.h \
-	Common/PassVisitor.proto.h \
 	Common/PersistentMap.h \
 	Common/ResolvProtoDump.hpp \
Index: c/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,1372 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// Keywords.cc --
-//
-// Author           : Thierry Delisle
-// Created On       : Mon Mar 13 12:41:22 2017
-// Last Modified By :
-// Last Modified On :
-// Update Count     : 10
-//
-
-#include "Concurrency/Keywords.h"
-
-#include <cassert>                        // for assert
-#include <string>                         // for string, operator==
-
-#include <iostream>
-
-#include "Common/Examine.h"               // for isMainFor
-#include "Common/PassVisitor.h"           // for PassVisitor
-#include "Common/SemanticError.h"         // for SemanticError
-#include "Common/utility.h"               // for deleteAll, map_range
-#include "CodeGen/OperatorTable.h"        // for isConstructor
-#include "ControlStruct/LabelGenerator.h" // for LebelGenerator
-#include "InitTweak/InitTweak.h"          // for getPointerBase
-#include "SynTree/LinkageSpec.h"          // for Cforall
-#include "SynTree/Constant.h"             // for Constant
-#include "SynTree/Declaration.h"          // for StructDecl, FunctionDecl, ObjectDecl
-#include "SynTree/Expression.h"           // for VariableExpr, ConstantExpr, Untype...
-#include "SynTree/Initializer.h"          // for SingleInit, ListInit, Initializer ...
-#include "SynTree/Label.h"                // for Label
-#include "SynTree/Statement.h"            // for CompoundStmt, DeclStmt, ExprStmt
-#include "SynTree/Type.h"                 // for StructInstType, Type, PointerType
-#include "SynTree/Visitor.h"              // for Visitor, acceptAll
-#include "Virtual/Tables.h"
-
-class Attribute;
-
-namespace Concurrency {
-	inline static std::string getTypeIdName( std::string const & exception_name ) {
-		return exception_name.empty() ? std::string() : Virtual::typeIdType( exception_name );
-	}
-	inline static std::string getVTableName( std::string const & exception_name ) {
-		return exception_name.empty() ? std::string() : Virtual::vtableTypeName( exception_name );
-	}
-
-	// Only detects threads constructed with the keyword thread.
-	inline static bool isThread( DeclarationWithType * decl ) {
-		Type * baseType = decl->get_type()->stripDeclarator();
-		StructInstType * instType = dynamic_cast<StructInstType *>( baseType );
-		if ( nullptr == instType ) { return false; }
-		return instType->baseStruct->is_thread();
-	}
-
-	//=============================================================================================
-	// Pass declarations
-	//=============================================================================================
-
-	//-----------------------------------------------------------------------------
-	//Handles sue type declarations :
-	// sue MyType {                             struct MyType {
-	// 	int data;                                  int data;
-	// 	a_struct_t more_data;                      a_struct_t more_data;
-	//                                =>             NewField_t newField;
-	// };                                        };
-	//                                           static inline NewField_t * getter_name( MyType * this ) { return &this->newField; }
-	//
-	class ConcurrentSueKeyword : public WithDeclsToAdd {
-	  public:
-
-		ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name,
-			std::string&& getter_name, std::string&& context_error, std::string&& exception_name,
-			bool needs_main, AggregateDecl::Aggregate cast_target ) :
-		  type_name( type_name ), field_name( field_name ), getter_name( getter_name ),
-		  context_error( context_error ), exception_name( exception_name ),
-		  typeid_name( getTypeIdName( exception_name ) ),
-		  vtable_name( getVTableName( exception_name ) ),
-		  needs_main( needs_main ), cast_target( cast_target ) {}
-
-		virtual ~ConcurrentSueKeyword() {}
-
-		Declaration * postmutate( StructDecl * decl );
-		DeclarationWithType * postmutate( FunctionDecl * decl );
-
-		void handle( StructDecl * );
-		void addTypeId( StructDecl * );
-		void addVtableForward( StructDecl * );
-		FunctionDecl * forwardDeclare( StructDecl * );
-		ObjectDecl * addField( StructDecl * );
-		void addRoutines( ObjectDecl *, FunctionDecl * );
-		void addLockUnlockRoutines( StructDecl * );
-
-		virtual bool is_target( StructDecl * decl ) = 0;
-
-		Expression * postmutate( KeywordCastExpr * cast );
-
-	  private:
-		const std::string type_name;
-		const std::string field_name;
-		const std::string getter_name;
-		const std::string context_error;
-		const std::string exception_name;
-		const std::string typeid_name;
-		const std::string vtable_name;
-		bool needs_main;
-		AggregateDecl::Aggregate cast_target;
-
-		StructDecl   * type_decl = nullptr;
-		FunctionDecl * dtor_decl = nullptr;
-		StructDecl * except_decl = nullptr;
-		StructDecl * typeid_decl = nullptr;
-		StructDecl * vtable_decl = nullptr;
-	};
-
-
-	//-----------------------------------------------------------------------------
-	//Handles thread type declarations :
-	// thread Mythread {                         struct MyThread {
-	// 	int data;                                  int data;
-	// 	a_struct_t more_data;                      a_struct_t more_data;
-	//                                =>             thread$ __thrd_d;
-	// };                                        };
-	//                                           static inline thread$ * get_thread( MyThread * this ) { return &this->__thrd_d; }
-	//
-	class ThreadKeyword final : public ConcurrentSueKeyword {
-	  public:
-
-	  	ThreadKeyword() : ConcurrentSueKeyword(
-			"thread$",
-			"__thrd",
-			"get_thread",
-			"thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
-			"ThreadCancelled",
-			true,
-			AggregateDecl::Thread
-		)
-		{}
-
-		virtual ~ThreadKeyword() {}
-
-		virtual bool is_target( StructDecl * decl ) override final { return decl->is_thread(); }
-
-		static void implement( std::list< Declaration * > & translationUnit ) {
-			PassVisitor< ThreadKeyword > impl;
-			mutateAll( translationUnit, impl );
-		}
-	};
-
-	//-----------------------------------------------------------------------------
-	//Handles coroutine type declarations :
-	// coroutine MyCoroutine {                   struct MyCoroutine {
-	// 	int data;                                  int data;
-	// 	a_struct_t more_data;                      a_struct_t more_data;
-	//                                =>             coroutine$ __cor_d;
-	// };                                        };
-	//                                           static inline coroutine$ * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
-	//
-	class CoroutineKeyword final : public ConcurrentSueKeyword {
-	  public:
-
-	  	CoroutineKeyword() : ConcurrentSueKeyword(
-			"coroutine$",
-			"__cor",
-			"get_coroutine",
-			"coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n",
-			"CoroutineCancelled",
-			true,
-			AggregateDecl::Coroutine
-		)
-		{}
-
-		virtual ~CoroutineKeyword() {}
-
-		virtual bool is_target( StructDecl * decl ) override final { return decl->is_coroutine(); }
-
-		static void implement( std::list< Declaration * > & translationUnit ) {
-			PassVisitor< CoroutineKeyword > impl;
-			mutateAll( translationUnit, impl );
-		}
-	};
-
-
-
-	//-----------------------------------------------------------------------------
-	//Handles monitor type declarations :
-	// monitor MyMonitor {                       struct MyMonitor {
-	// 	int data;                                  int data;
-	// 	a_struct_t more_data;                      a_struct_t more_data;
-	//                                =>             monitor$ __mon_d;
-	// };                                        };
-	//                                           static inline monitor$ * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
-	//
-	class MonitorKeyword final : public ConcurrentSueKeyword {
-	  public:
-
-	  	MonitorKeyword() : ConcurrentSueKeyword(
-			"monitor$",
-			"__mon",
-			"get_monitor",
-			"monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n",
-			"",
-			false,
-			AggregateDecl::Monitor
-		)
-		{}
-
-		virtual ~MonitorKeyword() {}
-
-		virtual bool is_target( StructDecl * decl ) override final { return decl->is_monitor(); }
-
-		static void implement( std::list< Declaration * > & translationUnit ) {
-			PassVisitor< MonitorKeyword > impl;
-			mutateAll( translationUnit, impl );
-		}
-	};
-
-	//-----------------------------------------------------------------------------
-	//Handles generator type declarations :
-	// generator MyGenerator {                   struct MyGenerator {
-	// 	int data;                                  int data;
-	// 	a_struct_t more_data;                      a_struct_t more_data;
-	//                                =>             int __gen_next;
-	// };                                        };
-	//
-	class GeneratorKeyword final : public ConcurrentSueKeyword {
-	  public:
-
-	  	GeneratorKeyword() : ConcurrentSueKeyword(
-			"generator$",
-			"__generator_state",
-			"get_generator",
-			"Unable to find builtin type generator$\n",
-			"",
-			true,
-			AggregateDecl::Generator
-		)
-		{}
-
-		virtual ~GeneratorKeyword() {}
-
-		virtual bool is_target( StructDecl * decl ) override final { return decl->is_generator(); }
-
-		static void implement( std::list< Declaration * > & translationUnit ) {
-			PassVisitor< GeneratorKeyword > impl;
-			mutateAll( translationUnit, impl );
-		}
-	};
-
-
-	//-----------------------------------------------------------------------------
-	class SuspendKeyword final : public WithStmtsToAdd, public WithGuards {
-	public:
-		SuspendKeyword() = default;
-		virtual ~SuspendKeyword() = default;
-
-		void  premutate( FunctionDecl * );
-		DeclarationWithType * postmutate( FunctionDecl * );
-
-		Statement * postmutate( SuspendStmt * );
-
-		static void implement( std::list< Declaration * > & translationUnit ) {
-			PassVisitor< SuspendKeyword > impl;
-			mutateAll( translationUnit, impl );
-		}
-
-	private:
-		bool is_real_suspend( FunctionDecl * );
-
-		Statement * make_generator_suspend( SuspendStmt * );
-		Statement * make_coroutine_suspend( SuspendStmt * );
-
-		struct LabelPair {
-			Label obj;
-			int   idx;
-		};
-
-		LabelPair make_label() {
-			labels.push_back( gen.newLabel("generator") );
-			return { labels.back(), int(labels.size()) };
-		}
-
-		DeclarationWithType * in_generator = nullptr;
-		FunctionDecl * decl_suspend = nullptr;
-		std::vector<Label> labels;
-		ControlStruct::LabelGenerator & gen = *ControlStruct::LabelGenerator::getGenerator();
-	};
-
-	//-----------------------------------------------------------------------------
-	//Handles mutex routines definitions :
-	// void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
-	// 	                                                                 monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) };
-	// 	                                                                 monitor_guard_t __guard = { __monitors, 2 };
-	//    /*Some code*/                                       =>           /*Some code*/
-	// }                                                               }
-	//
-	class MutexKeyword final {
-	  public:
-
-		void postvisit( FunctionDecl * decl );
-		void postvisit(   StructDecl * decl );
-		Statement * postmutate( MutexStmt * stmt );
-
-		std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first );
-		void validate( DeclarationWithType * );
-		void addDtorStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
-		void addStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
-		void addStatements( CompoundStmt * body, const std::list<Expression * > & args );
-		void addThreadDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args );
-
-		static void implement( std::list< Declaration * > & translationUnit ) {
-			PassVisitor< MutexKeyword > impl;
-			acceptAll( translationUnit, impl );
-			mutateAll( translationUnit, impl );
-		}
-
-	  private:
-	  	StructDecl* monitor_decl = nullptr;
-		StructDecl* guard_decl = nullptr;
-		StructDecl* dtor_guard_decl = nullptr;
-		StructDecl* thread_guard_decl = nullptr;
-		StructDecl* lock_guard_decl = nullptr;
-
-		static std::unique_ptr< Type > generic_func;
-	};
-
-	std::unique_ptr< Type > MutexKeyword::generic_func = std::unique_ptr< Type >(
-		new FunctionType(
-			noQualifiers,
-			true
-		)
-	);
-
-	//-----------------------------------------------------------------------------
-	//Handles mutex routines definitions :
-	// void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
-	// 	                                                                 monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) };
-	// 	                                                                 monitor_guard_t __guard = { __monitors, 2 };
-	//    /*Some code*/                                       =>           /*Some code*/
-	// }                                                               }
-	//
-	class ThreadStarter final {
-	  public:
-
-		void postvisit( FunctionDecl * decl );
-		void previsit ( StructDecl   * decl );
-
-		void addStartStatement( FunctionDecl * decl, DeclarationWithType * param );
-
-		static void implement( std::list< Declaration * > & translationUnit ) {
-			PassVisitor< ThreadStarter > impl;
-			acceptAll( translationUnit, impl );
-		}
-
-	  private :
-		bool thread_ctor_seen = false;
-		StructDecl * thread_decl = nullptr;
-	};
-
-	//=============================================================================================
-	// General entry routine
-	//=============================================================================================
-	void applyKeywords( std::list< Declaration * > & translationUnit ) {
-		ThreadKeyword	::implement( translationUnit );
-		CoroutineKeyword	::implement( translationUnit );
-		MonitorKeyword	::implement( translationUnit );
-		GeneratorKeyword  ::implement( translationUnit );
-		SuspendKeyword    ::implement( translationUnit );
-	}
-
-	void implementMutexFuncs( std::list< Declaration * > & translationUnit ) {
-		MutexKeyword	::implement( translationUnit );
-	}
-
-	void implementThreadStarter( std::list< Declaration * > & translationUnit ) {
-		ThreadStarter	::implement( translationUnit );
-	}
-
-	//=============================================================================================
-	// Generic keyword implementation
-	//=============================================================================================
-	void fixupGenerics(FunctionType * func, StructDecl * decl) {
-		cloneAll(decl->parameters, func->forall);
-		for ( TypeDecl * td : func->forall ) {
-			strict_dynamic_cast<StructInstType*>(
-				func->parameters.front()->get_type()->stripReferences()
-			)->parameters.push_back(
-				new TypeExpr( new TypeInstType( noQualifiers, td->name, td ) )
-			);
-		}
-	}
-
-	Declaration * ConcurrentSueKeyword::postmutate(StructDecl * decl) {
-		if( decl->name == type_name && decl->body ) {
-			assert( !type_decl );
-			type_decl = decl;
-		}
-		else if ( is_target(decl) ) {
-			handle( decl );
-		}
-		else if ( !except_decl && exception_name == decl->name && decl->body ) {
-			except_decl = decl;
-		}
-		else if ( !typeid_decl && typeid_name == decl->name && decl->body ) {
-			typeid_decl = decl;
-		}
-		else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
-			vtable_decl = decl;
-		}
-		// Might be able to get ride of is target.
-		assert( is_target(decl) == (cast_target == decl->kind) );
-		return decl;
-	}
-
-	DeclarationWithType * ConcurrentSueKeyword::postmutate( FunctionDecl * decl ) {
-		if ( type_decl && isDestructorFor( decl, type_decl ) )
-			dtor_decl = decl;
-		else if ( vtable_name.empty() || !decl->has_body() )
-			;
-		else if ( auto param = isMainFor( decl, cast_target ) ) {
-			if ( !vtable_decl ) {
-				SemanticError( decl, context_error );
-			}
-			// Should be safe because of isMainFor.
-			StructInstType * struct_type = static_cast<StructInstType *>(
-				static_cast<ReferenceType *>( param->get_type() )->base );
-			assert( struct_type );
-
-			std::list< Expression * > poly_args = { new TypeExpr( struct_type->clone() ) };
-			ObjectDecl * vtable_object = Virtual::makeVtableInstance(
-				"_default_vtable_object_declaration",
-				vtable_decl->makeInst( poly_args ), struct_type, nullptr );
-			declsToAddAfter.push_back( vtable_object );
-			declsToAddAfter.push_back(
-				new ObjectDecl(
-					Virtual::concurrentDefaultVTableName(),
-					noStorageClasses,
-					LinkageSpec::Cforall,
-					/* bitfieldWidth */ nullptr,
-					new ReferenceType( Type::Const, vtable_object->type->clone() ),
-					new SingleInit( new VariableExpr( vtable_object ) )
-				)
-			);
-			declsToAddAfter.push_back( Virtual::makeGetExceptionFunction(
-				vtable_object, except_decl->makeInst( std::move( poly_args ) )
-			) );
-		}
-
-		return decl;
-	}
-
-	Expression * ConcurrentSueKeyword::postmutate( KeywordCastExpr * cast ) {
-		if ( cast_target == cast->target ) {
-			// convert (thread &)t to (thread$ &)*get_thread(t), etc.
-			if( !type_decl ) SemanticError( cast, context_error );
-			if( !dtor_decl ) SemanticError( cast, context_error );
-			assert( cast->result == nullptr );
-			cast->set_result( new ReferenceType( noQualifiers, new StructInstType( noQualifiers, type_decl ) ) );
-			cast->concrete_target.field  = field_name;
-			cast->concrete_target.getter = getter_name;
-		}
-		return cast;
-	}
-
-	void ConcurrentSueKeyword::handle( StructDecl * decl ) {
-		if( ! decl->body ) return;
-
-		if( !type_decl ) SemanticError( decl, context_error );
-		if( !dtor_decl ) SemanticError( decl, context_error );
-
-		if ( !exception_name.empty() ) {
-			if( !typeid_decl ) SemanticError( decl, context_error );
-			if( !vtable_decl ) SemanticError( decl, context_error );
-
-			addTypeId( decl );
-			addVtableForward( decl );
-		}
-		FunctionDecl * func = forwardDeclare( decl );
-		ObjectDecl * field = addField( decl );
-
-		// add get_.* routine
-		addRoutines( field, func );
-		// add lock/unlock routines to monitors for use by mutex stmt
-		addLockUnlockRoutines( decl );
-	}
-
-	void ConcurrentSueKeyword::addTypeId( StructDecl * decl ) {
-		assert( typeid_decl );
-		StructInstType typeid_type( Type::Const, typeid_decl );
-		typeid_type.parameters.push_back( new TypeExpr(
-			new StructInstType( noQualifiers, decl )
-			) );
-		declsToAddBefore.push_back( Virtual::makeTypeIdInstance( &typeid_type ) );
-	}
-
-	void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
-		assert( vtable_decl );
-		std::list< Expression * > poly_args = {
-			new TypeExpr( new StructInstType( noQualifiers, decl ) ),
-		};
-		declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
-			vtable_decl->makeInst( poly_args ),
-			except_decl->makeInst( poly_args )
-		) );
-		ObjectDecl * vtable_object = Virtual::makeVtableForward(
-			"_default_vtable_object_declaration",
-			vtable_decl->makeInst( std::move( poly_args ) ) );
-		declsToAddBefore.push_back( vtable_object );
-		declsToAddBefore.push_back(
-			new ObjectDecl(
-				Virtual::concurrentDefaultVTableName(),
-				Type::StorageClasses( Type::Extern ),
-				LinkageSpec::Cforall,
-				/* bitfieldWidth */ nullptr,
-				new ReferenceType( Type::Const, vtable_object->type->clone() ),
-				/* init */ nullptr
-			)
-		);
-	}
-
-	FunctionDecl * ConcurrentSueKeyword::forwardDeclare( StructDecl * decl ) {
-
-		StructDecl * forward = decl->clone();
-		forward->set_body( false );
-		deleteAll( forward->get_members() );
-		forward->get_members().clear();
-
-		FunctionType * get_type = new FunctionType( noQualifiers, false );
-		ObjectDecl * this_decl = new ObjectDecl(
-			"this",
-			noStorageClasses,
-			LinkageSpec::Cforall,
-			nullptr,
-			new ReferenceType(
-				noQualifiers,
-				new StructInstType(
-					noQualifiers,
-					decl
-				)
-			),
-			nullptr
-		);
-
-		get_type->get_parameters().push_back( this_decl->clone() );
-		get_type->get_returnVals().push_back(
-			new ObjectDecl(
-				"ret",
-				noStorageClasses,
-				LinkageSpec::Cforall,
-				nullptr,
-				new PointerType(
-					noQualifiers,
-					new StructInstType(
-						noQualifiers,
-						type_decl
-					)
-				),
-				nullptr
-			)
-		);
-		fixupGenerics(get_type, decl);
-
-		FunctionDecl * get_decl = new FunctionDecl(
-			getter_name,
-			Type::Static,
-			LinkageSpec::Cforall,
-			get_type,
-			nullptr,
-			{ new Attribute("const") },
-			Type::Inline
-		);
-
-		FunctionDecl * main_decl = nullptr;
-
-		if( needs_main ) {
-			FunctionType * main_type = new FunctionType( noQualifiers, false );
-
-			main_type->get_parameters().push_back( this_decl->clone() );
-
-			main_decl = new FunctionDecl(
-				"main",
-				noStorageClasses,
-				LinkageSpec::Cforall,
-				main_type,
-				nullptr
-			);
-			fixupGenerics(main_type, decl);
-		}
-
-		delete this_decl;
-
-		declsToAddBefore.push_back( forward );
-		if( needs_main ) declsToAddBefore.push_back( main_decl );
-		declsToAddBefore.push_back( get_decl );
-
-		return get_decl;
-	}
-
-	ObjectDecl * ConcurrentSueKeyword::addField( StructDecl * decl ) {
-		ObjectDecl * field = new ObjectDecl(
-			field_name,
-			noStorageClasses,
-			LinkageSpec::Cforall,
-			nullptr,
-			new StructInstType(
-				noQualifiers,
-				type_decl
-			),
-			nullptr
-		);
-
-		decl->get_members().push_back( field );
-
-		return field;
-	}
-
-	// This function adds the get_.* routine body for coroutines, monitors etc
-	// 		after their corresponding struct has been made
-	void ConcurrentSueKeyword::addRoutines( ObjectDecl * field, FunctionDecl * func ) {
-		CompoundStmt * statement = new CompoundStmt();
-		statement->push_back(
-			new ReturnStmt(
-				new AddressExpr(
-					new MemberExpr(
-						field,
-						new CastExpr(
-							new VariableExpr( func->get_functionType()->get_parameters().front() ),
-							func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone(),
-							false
-						)
-					)
-				)
-			)
-		);
-
-		FunctionDecl * get_decl = func->clone();
-
-		get_decl->set_statements( statement );
-
-		declsToAddAfter.push_back( get_decl );
-	}
-
-	// Generates lock/unlock routines for monitors to be used by mutex stmts
-	void ConcurrentSueKeyword::addLockUnlockRoutines( StructDecl * decl ) {
-		// this routine will be called for all ConcurrentSueKeyword children so only continue if we are a monitor
-		if ( !decl->is_monitor() ) return;
-
-		FunctionType * lock_fn_type = new FunctionType( noQualifiers, false );
-		FunctionType * unlock_fn_type = new FunctionType( noQualifiers, false );
-
-		// create this ptr parameter for both routines
-		ObjectDecl * this_decl = new ObjectDecl(
-			"this",
-			noStorageClasses,
-			LinkageSpec::Cforall,
-			nullptr,
-			new ReferenceType(
-				noQualifiers,
-				new StructInstType(
-					noQualifiers,
-					decl
-				)
-			),
-			nullptr
-		);
-
-		lock_fn_type->get_parameters().push_back( this_decl->clone() );
-		unlock_fn_type->get_parameters().push_back( this_decl->clone() );
-		fixupGenerics(lock_fn_type, decl);
-		fixupGenerics(unlock_fn_type, decl);
-
-		delete this_decl;
-
-
-		//////////////////////////////////////////////////////////////////////
-		// The following generates this lock routine for all monitors
-		/*
-			void lock (monitor_t & this) {
-				lock(get_monitor(this));
-			}
-		*/
-		FunctionDecl * lock_decl = new FunctionDecl(
-			"lock",
-			Type::Static,
-			LinkageSpec::Cforall,
-			lock_fn_type,
-			nullptr,
-			{ },
-			Type::Inline
-		);
-
-		UntypedExpr * get_monitor_lock =  new UntypedExpr (
-			new NameExpr( "get_monitor" ),
-			{ new VariableExpr( lock_fn_type->get_parameters().front() ) }
-		);
-
-		CompoundStmt * lock_statement = new CompoundStmt();
-		lock_statement->push_back(
-			new ExprStmt(
-				new UntypedExpr (
-					new NameExpr( "lock" ),
-					{
-						get_monitor_lock
-					}
-				)
-			)
-		);
-		lock_decl->set_statements( lock_statement );
-
-		//////////////////////////////////////////////////////////////////
-		// The following generates this routine for all monitors
-		/*
-			void unlock (monitor_t & this) {
-				unlock(get_monitor(this));
-			}
-		*/
-		FunctionDecl * unlock_decl = new FunctionDecl(
-			"unlock",
-			Type::Static,
-			LinkageSpec::Cforall,
-			unlock_fn_type,
-			nullptr,
-			{ },
-			Type::Inline
-		);
-
-		CompoundStmt * unlock_statement = new CompoundStmt();
-
-		UntypedExpr * get_monitor_unlock =  new UntypedExpr (
-			new NameExpr( "get_monitor" ),
-			{ new VariableExpr( unlock_fn_type->get_parameters().front() ) }
-		);
-
-		unlock_statement->push_back(
-			new ExprStmt(
-				new UntypedExpr(
-					new NameExpr( "unlock" ),
-					{
-						get_monitor_unlock
-					}
-				)
-			)
-		);
-		unlock_decl->set_statements( unlock_statement );
-
-		// pushes routines to declsToAddAfter to add at a later time
-		declsToAddAfter.push_back( lock_decl );
-		declsToAddAfter.push_back( unlock_decl );
-	}
-
-	//=============================================================================================
-	// Suspend keyword implementation
-	//=============================================================================================
-	bool SuspendKeyword::is_real_suspend( FunctionDecl * func ) {
-		if(isMangled(func->linkage)) return false; // the real suspend isn't mangled
-		if(func->name != "__cfactx_suspend") return false; // the real suspend has a specific name
-		if(func->type->parameters.size() != 0) return false; // Too many parameters
-		if(func->type->returnVals.size() != 0) return false; // Too many return values
-
-		return true;
-	}
-
-	void SuspendKeyword::premutate( FunctionDecl * func ) {
-		GuardValue(in_generator);
-		in_generator = nullptr;
-
-		// Is this the real suspend?
-		if(is_real_suspend(func)) {
-			decl_suspend = decl_suspend ? decl_suspend : func;
-			return;
-		}
-
-		// Is this the main of a generator?
-		auto param = isMainFor( func, AggregateDecl::Aggregate::Generator );
-		if(!param) return;
-
-		if(func->type->returnVals.size() != 0) SemanticError(func->location, "Generator main must return void");
-
-		in_generator = param;
-		GuardValue(labels);
-		labels.clear();
-	}
-
-	DeclarationWithType * SuspendKeyword::postmutate( FunctionDecl * func ) {
-		if( !func->statements ) return func; // Not the actual definition, don't do anything
-		if( !in_generator     ) return func; // Not in a generator, don't do anything
-		if( labels.empty()    ) return func; // Generator has no states, nothing to do, could throw a warning
-
-		// This is a generator main, we need to add the following code to the top
-		// static void * __generator_labels[] = {&&s0, &&s1, ...};
-		// goto * __generator_labels[gen.__generator_state];
-		const auto & loc = func->location;
-
-		const auto first_label = gen.newLabel("generator");
-
-		// for each label add to declaration
-		std::list<Initializer*> inits = { new SingleInit( new LabelAddressExpr( first_label ) ) };
-		for(const auto & label : labels) {
-			inits.push_back(
-				new SingleInit(
-					new LabelAddressExpr( label )
-				)
-			);
-		}
-		auto init = new ListInit(std::move(inits), noDesignators, true);
-		labels.clear();
-
-		// create decl
-		auto decl = new ObjectDecl(
-			"__generator_labels",
-			Type::StorageClasses( Type::Static ),
-			LinkageSpec::AutoGen,
-			nullptr,
-			new ArrayType(
-				Type::Qualifiers(),
-				new PointerType(
-					Type::Qualifiers(),
-					new VoidType( Type::Qualifiers() )
-				),
-				nullptr,
-				false, false
-			),
-			init
-		);
-
-		// create the goto
-		assert(in_generator);
-
-		auto go_decl = new ObjectDecl(
-			"__generator_label",
-			noStorageClasses,
-			LinkageSpec::AutoGen,
-			nullptr,
-			new PointerType(
-				Type::Qualifiers(),
-				new VoidType( Type::Qualifiers() )
-			),
-			new SingleInit(
-				new UntypedExpr(
-					new NameExpr("?[?]"),
-					{
-						new NameExpr("__generator_labels"),
-						new UntypedMemberExpr(
-							new NameExpr("__generator_state"),
-							new VariableExpr( in_generator )
-						)
-					}
-				)
-			)
-		);
-		go_decl->location = loc;
-
-		auto go = new BranchStmt(
-			new VariableExpr( go_decl ),
-			BranchStmt::Goto
-		);
-		go->location = loc;
-		go->computedTarget->location = loc;
-
-		auto noop = new NullStmt({ first_label });
-		noop->location = loc;
-
-		// wrap everything in a nice compound
-		auto body = new CompoundStmt({
-			new DeclStmt( decl ),
-			new DeclStmt( go_decl ),
-			go,
-			noop,
-			func->statements
-		});
-		body->location   = loc;
-		func->statements = body;
-
-		return func;
-	}
-
-	Statement * SuspendKeyword::postmutate( SuspendStmt * stmt ) {
-		SuspendStmt::Type type = stmt->type;
-		if(type == SuspendStmt::None) {
-			// This suspend has a implicit target, find it
-			type = in_generator ? SuspendStmt::Generator : SuspendStmt::Coroutine;
-		}
-
-		// Check that the target makes sense
-		if(!in_generator && type == SuspendStmt::Generator) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type.");
-
-		// Act appropriately
-		switch(type) {
-			case SuspendStmt::Generator: return make_generator_suspend(stmt);
-			case SuspendStmt::Coroutine: return make_coroutine_suspend(stmt);
-			default: abort();
-		}
-	}
-
-	Statement * SuspendKeyword::make_generator_suspend( SuspendStmt * stmt ) {
-		assert(in_generator);
-		// Target code is :
-		//   gen.__generator_state = X;
-		//   { THEN }
-		//   return;
-		//   __gen_X:;
-
-		// Save the location and delete the old statement, we only need the location from this point on
-		auto loc = stmt->location;
-
-		// Build the label and get its index
-		auto label = make_label();
-
-		// Create the context saving statement
-		auto save = new ExprStmt( new UntypedExpr(
-			new NameExpr( "?=?" ),
-			{
-				new UntypedMemberExpr(
-					new NameExpr("__generator_state"),
-					new VariableExpr( in_generator )
-				),
-				new ConstantExpr(
-					Constant::from_int( label.idx )
-				)
-			}
-		));
-		assert(save->expr);
-		save->location = loc;
-		stmtsToAddBefore.push_back( save );
-
-		// if we have a then add it here
-		auto then = stmt->then;
-		stmt->then = nullptr;
-		delete stmt;
-		if(then) stmtsToAddBefore.push_back( then );
-
-		// Create the return statement
-		auto ret = new ReturnStmt( nullptr );
-		ret->location = loc;
-		stmtsToAddBefore.push_back( ret );
-
-		// Create the null statement with the created label
-		auto noop = new NullStmt({ label.obj });
-		noop->location = loc;
-
-		// Return the null statement to take the place of the previous statement
-		return noop;
-	}
-
-	Statement * SuspendKeyword::make_coroutine_suspend( SuspendStmt * stmt ) {
-		if(stmt->then) SemanticError( stmt->location, "Compound statement following coroutines is not implemented.");
-
-		// Save the location and delete the old statement, we only need the location from this point on
-		auto loc = stmt->location;
-		delete stmt;
-
-		// Create the call expression
-		if(!decl_suspend) SemanticError( loc, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n");
-		auto expr = new UntypedExpr( VariableExpr::functionPointer( decl_suspend ) );
-		expr->location = loc;
-
-		// Change this statement into a regular expr
-		assert(expr);
-		auto nstmt = new ExprStmt( expr );
-		nstmt->location = loc;
-		return nstmt;
-	}
-
-
-	//=============================================================================================
-	// Mutex keyword implementation
-	//=============================================================================================
-
-	void MutexKeyword::postvisit(FunctionDecl* decl) {
-
-		bool first = false;
-		std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first );
-		bool const isDtor = CodeGen::isDestructor( decl->name );
-
-		// Is this function relevant to monitors
-		if( mutexArgs.empty() ) {
-			// If this is the destructor for a monitor it must be mutex
-			if(isDtor) {
-				// This reflects MutexKeyword::validate, except does not produce an error.
-				Type* ty = decl->get_functionType()->get_parameters().front()->get_type();
-
-				// If it's a copy, it's not a mutex
-				ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
-				if( ! rty ) return;
-
-				// If we are not pointing directly to a type, it's not a mutex
-				Type* base = rty->get_base();
-				if( dynamic_cast< ReferenceType * >( base ) ) return;
-				if( dynamic_cast< PointerType * >( base ) ) return;
-
-				// Check if its a struct
-				StructInstType * baseStruct = dynamic_cast< StructInstType * >( base );
-				if( !baseStruct ) return;
-
-				// Check if its a monitor
-				if(baseStruct->baseStruct->is_monitor() || baseStruct->baseStruct->is_thread())
-					SemanticError( decl, "destructors for structures declared as \"monitor\" must use mutex parameters\n" );
-			}
-			return;
-		}
-
-		// Monitors can't be constructed with mutual exclusion
-		if( CodeGen::isConstructor(decl->name) && !first ) SemanticError( decl, "constructors cannot have mutex parameters" );
-
-		// It makes no sense to have multiple mutex parameters for the destructor
-		if( isDtor && mutexArgs.size() != 1 ) SemanticError( decl, "destructors can only have 1 mutex argument" );
-
-		// Make sure all the mutex arguments are monitors
-		for(auto arg : mutexArgs) {
-			validate( arg );
-		}
-
-		// Check if we need to instrument the body
-		CompoundStmt* body = decl->get_statements();
-		if( ! body ) return;
-
-		// Do we have the required headers
-		if( !monitor_decl || !guard_decl || !dtor_guard_decl )
-			SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor.hfa>\n" );
-
-		// Instrument the body
-		if ( isDtor && isThread( mutexArgs.front() ) ) {
-			if( !thread_guard_decl ) {
-				SemanticError( decl, "thread destructor requires threads to be in scope, add #include <thread.hfa>\n" );
-			}
-			addThreadDtorStatements( decl, body, mutexArgs );
-		}
-		else if ( isDtor ) {
-			addDtorStatements( decl, body, mutexArgs );
-		}
-		else {
-			addStatements( decl, body, mutexArgs );
-		}
-	}
-
-	void MutexKeyword::postvisit(StructDecl* decl) {
-
-		if( decl->name == "monitor$" && decl->body ) {
-			assert( !monitor_decl );
-			monitor_decl = decl;
-		}
-		else if( decl->name == "monitor_guard_t" && decl->body ) {
-			assert( !guard_decl );
-			guard_decl = decl;
-		}
-		else if( decl->name == "monitor_dtor_guard_t" && decl->body ) {
-			assert( !dtor_guard_decl );
-			dtor_guard_decl = decl;
-		}
-		else if( decl->name == "thread_dtor_guard_t" && decl->body ) {
-			assert( !thread_guard_decl );
-			thread_guard_decl = decl;
-		}
-		else if ( decl->name == "__mutex_stmt_lock_guard" && decl->body ) {
-			assert( !lock_guard_decl );
-			lock_guard_decl = decl;
-		}
-	}
-
-	Statement * MutexKeyword::postmutate( MutexStmt * stmt ) {
-		std::list<Statement *> stmtsForCtor;
-		stmtsForCtor.push_back(stmt->stmt);
-		CompoundStmt * body = new CompoundStmt( stmtsForCtor );
-		addStatements( body, stmt->mutexObjs);
-		return body;
-	}
-
-	std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl, bool & first ) {
-		std::list<DeclarationWithType*> mutexArgs;
-
-		bool once = true;
-		for( auto arg : decl->get_functionType()->get_parameters()) {
-			//Find mutex arguments
-			Type* ty = arg->get_type();
-			if( ! ty->get_mutex() ) continue;
-
-			if(once) {first = true;}
-			once = false;
-
-			//Append it to the list
-			mutexArgs.push_back( arg );
-		}
-
-		return mutexArgs;
-	}
-
-	void MutexKeyword::validate( DeclarationWithType * arg ) {
-		Type* ty = arg->get_type();
-
-		//Makes sure it's not a copy
-		ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
-		if( ! rty ) SemanticError( arg, "Mutex argument must be of reference type " );
-
-		//Make sure the we are pointing directly to a type
-		Type* base = rty->get_base();
-		if( dynamic_cast< ReferenceType * >( base ) ) SemanticError( arg, "Mutex argument have exactly one level of indirection " );
-		if( dynamic_cast< PointerType * >( base ) ) SemanticError( arg, "Mutex argument have exactly one level of indirection " );
-
-		//Make sure that typed isn't mutex
-		if( base->get_mutex() ) SemanticError( arg, "mutex keyword may only appear once per argument " );
-	}
-
-	void MutexKeyword::addDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
-		Type * arg_type = args.front()->get_type()->clone();
-		arg_type->set_mutex( false );
-
-		ObjectDecl * monitors = new ObjectDecl(
-			"__monitor",
-			noStorageClasses,
-			LinkageSpec::Cforall,
-			nullptr,
-			new PointerType(
-				noQualifiers,
-				new StructInstType(
-					noQualifiers,
-					monitor_decl
-				)
-			),
-			new SingleInit( new UntypedExpr(
-				new NameExpr( "get_monitor" ),
-				{  new CastExpr( new VariableExpr( args.front() ), arg_type, false ) }
-			))
-		);
-
-		assert(generic_func);
-
-		//in reverse order :
-		// monitor_dtor_guard_t __guard = { __monitors, func };
-		body->push_front(
-			new DeclStmt( new ObjectDecl(
-				"__guard",
-				noStorageClasses,
-				LinkageSpec::Cforall,
-				nullptr,
-				new StructInstType(
-					noQualifiers,
-					dtor_guard_decl
-				),
-				new ListInit(
-					{
-						new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
-						new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ),
-						new SingleInit( new ConstantExpr( Constant::from_bool( false ) ) )
-					},
-					noDesignators,
-					true
-				)
-			))
-		);
-
-		//monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) };
-		body->push_front( new DeclStmt( monitors ) );
-	}
-
-	void MutexKeyword::addThreadDtorStatements(
-			FunctionDecl*, CompoundStmt * body,
-			const std::list<DeclarationWithType * > & args ) {
-		assert( args.size() == 1 );
-		DeclarationWithType * arg = args.front();
-		Type * arg_type = arg->get_type()->clone();
-		assert( arg_type->get_mutex() );
-		arg_type->set_mutex( false );
-
-		// thread_dtor_guard_t __guard = { this, intptr( 0 ) };
-		body->push_front(
-			new DeclStmt( new ObjectDecl(
-				"__guard",
-				noStorageClasses,
-				LinkageSpec::Cforall,
-				nullptr,
-				new StructInstType(
-					noQualifiers,
-					thread_guard_decl
-				),
-				new ListInit(
-					{
-						new SingleInit( new CastExpr( new VariableExpr( arg ), arg_type ) ),
-						new SingleInit( new UntypedExpr(
-							new NameExpr( "intptr" ), {
-								new ConstantExpr( Constant::from_int( 0 ) ),
-							}
-						) ),
-					},
-					noDesignators,
-					true
-				)
-			))
-		);
-	}
-
-	void MutexKeyword::addStatements( CompoundStmt * body, const std::list<Expression * > & args ) {
-		ObjectDecl * monitors = new ObjectDecl(
-			"__monitors",
-			noStorageClasses,
-			LinkageSpec::Cforall,
-			nullptr,
-			new ArrayType(
-				noQualifiers,
-				new PointerType(
-					noQualifiers,
-					//new TypeofType( noQualifiers, args.front()->clone() )
-					new TypeofType( noQualifiers, new UntypedExpr(
-							new NameExpr( "__get_mutexstmt_lock_type" ),
-							{ args.front()->clone() }
-						)
-					)
-				),
-				new ConstantExpr( Constant::from_ulong( args.size() ) ),
-				false,
-				false
-			),
-			new ListInit(
-				map_range < std::list<Initializer*> > ( args, [](Expression * var ){
-					return new SingleInit( new UntypedExpr(
-							new NameExpr( "__get_mutexstmt_lock_ptr" ),
-							{ var }
-					) );
-					//return new SingleInit( new AddressExpr( var ) );
-				})
-			)
-		);
-
-		StructInstType * lock_guard_struct = new StructInstType( noQualifiers, lock_guard_decl );
-		TypeExpr * lock_type_expr = new TypeExpr(
-			new TypeofType( noQualifiers, new UntypedExpr(
-				new NameExpr( "__get_mutexstmt_lock_type" ),
-				{ args.front()->clone() }
-				)
-			)
-		);
-
-		lock_guard_struct->parameters.push_back( lock_type_expr ) ;
-
-		// in reverse order :
-		// monitor_guard_t __guard = { __monitors, # };
-		body->push_front(
-			new DeclStmt( new ObjectDecl(
-				"__guard",
-				noStorageClasses,
-				LinkageSpec::Cforall,
-				nullptr,
-				lock_guard_struct,
-				new ListInit(
-					{
-						new SingleInit( new VariableExpr( monitors ) ),
-						new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) )
-					},
-					noDesignators,
-					true
-				)
-			))
-		);
-
-		//monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) };
-		body->push_front( new DeclStmt( monitors) );
-	}
-
-	void MutexKeyword::addStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
-		ObjectDecl * monitors = new ObjectDecl(
-			"__monitors",
-			noStorageClasses,
-			LinkageSpec::Cforall,
-			nullptr,
-			new ArrayType(
-				noQualifiers,
-				new PointerType(
-					noQualifiers,
-					new StructInstType(
-						noQualifiers,
-						monitor_decl
-					)
-				),
-				new ConstantExpr( Constant::from_ulong( args.size() ) ),
-				false,
-				false
-			),
-			new ListInit(
-				map_range < std::list<Initializer*> > ( args, [](DeclarationWithType * var ){
-					Type * type = var->get_type()->clone();
-					type->set_mutex( false );
-					return new SingleInit( new UntypedExpr(
-						new NameExpr( "get_monitor" ),
-						{  new CastExpr( new VariableExpr( var ), type, false ) }
-					) );
-				})
-			)
-		);
-
-		assert(generic_func);
-
-		// in reverse order :
-		// monitor_guard_t __guard = { __monitors, #, func };
-		body->push_front(
-			new DeclStmt( new ObjectDecl(
-				"__guard",
-				noStorageClasses,
-				LinkageSpec::Cforall,
-				nullptr,
-				new StructInstType(
-					noQualifiers,
-					guard_decl
-				),
-				new ListInit(
-					{
-						new SingleInit( new VariableExpr( monitors ) ),
-						new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) ),
-						new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) )
-					},
-					noDesignators,
-					true
-				)
-			))
-		);
-
-		//monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) };
-		body->push_front( new DeclStmt( monitors) );
-	}
-
-	//=============================================================================================
-	// General entry routine
-	//=============================================================================================
-	void ThreadStarter::previsit( StructDecl * decl ) {
-		if( decl->name == "thread$" && decl->body ) {
-			assert( !thread_decl );
-			thread_decl = decl;
-		}
-	}
-
-	void ThreadStarter::postvisit(FunctionDecl * decl) {
-		if( ! CodeGen::isConstructor(decl->name) ) return;
-
-		Type * typeof_this = InitTweak::getTypeofThis(decl->type);
-		StructInstType * ctored_type = dynamic_cast< StructInstType * >( typeof_this );
-		if( ctored_type && ctored_type->baseStruct == thread_decl ) {
-			thread_ctor_seen = true;
-		}
-
-		DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
-		auto type  = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
-		if( type && type->get_baseStruct()->is_thread() ) {
-			if( !thread_decl || !thread_ctor_seen ) {
-				SemanticError( type->get_baseStruct()->location, "thread keyword requires threads to be in scope, add #include <thread.hfa>");
-			}
-
-			addStartStatement( decl, param );
-		}
-	}
-
-	void ThreadStarter::addStartStatement( FunctionDecl * decl, DeclarationWithType * param ) {
-		CompoundStmt * stmt = decl->get_statements();
-
-		if( ! stmt ) return;
-
-		stmt->push_back(
-			new ExprStmt(
-				new UntypedExpr(
-					new NameExpr( "__thrd_start" ),
-					{ new VariableExpr( param ), new NameExpr("main") }
-				)
-			)
-		);
-	}
-};
-
-// Local Variables: //
-// mode: c //
-// tab-width: 4 //
-// End: //
-
Index: c/Concurrency/Waitfor.cc
===================================================================
--- src/Concurrency/Waitfor.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,598 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// Waitfor.cc --
-//
-// Author           : Thierry Delisle
-// Created On       : Mon Aug 28 11:06:52 2017
-// Last Modified By :
-// Last Modified On :
-// Update Count     : 12
-//
-
-#include "Concurrency/Keywords.h"
-
-#include <cassert>                 // for assert
-#include <string>                  // for string, operator==
-
-using namespace std::string_literals;
-
-#include "Common/PassVisitor.h"    // for PassVisitor
-#include "Common/SemanticError.h"  // for SemanticError
-#include "Common/UniqueName.h"	   // for UniqueName
-#include "Common/utility.h"        // for deleteAll, map_range
-#include "CodeGen/OperatorTable.h" // for isConstructor
-#include "InitTweak/InitTweak.h"   // for getPointerBase
-#include "ResolvExpr/Resolver.h"   // for findVoidExpression
-#include "SynTree/LinkageSpec.h"   // for Cforall
-#include "SynTree/Constant.h"      // for Constant
-#include "SynTree/Declaration.h"   // for StructDecl, FunctionDecl, ObjectDecl
-#include "SynTree/Expression.h"    // for VariableExpr, ConstantExpr, Untype...
-#include "SynTree/Initializer.h"   // for SingleInit, ListInit, Initializer ...
-#include "SynTree/Label.h"         // for Label
-#include "SynTree/Statement.h"     // for CompoundStmt, DeclStmt, ExprStmt
-#include "SynTree/Type.h"          // for StructInstType, Type, PointerType
-#include "SynTree/Visitor.h"       // for Visitor, acceptAll
-
-class Attribute;
-/*
-void foo() {
-	while( true ) {
-		when( a < 1 ) waitfor( f : a ) { bar(); }
-		or timeout( swagl() );
-		or waitfor( g : a ) { baz(); }
-		or waitfor( ^?{} : a ) { break; }
-		or waitfor( ^?{} ) { break; }
-	}
-}
-
-void f(int i, float f, A & mutex b, struct foo *  );
-void f(int );
-
-
-                      |  |
-                      |  |
-                      |  |
-                      |  |
-                      |  |
-                    \ |  | /
-                     \    /
-                      \  /
-                       \/
-
-
-void foo() {
-	while( true ) {
-		{
-			acceptable_t acceptables[3];
-			if( a < 1 ) {
-				acceptables[0].func = f;
-				acceptables[0].mon = a;
-			}
-			acceptables[1].func = g;
-			acceptables[1].mon = a;
-
-			acceptables[2].func = f;
-			acceptables[2].mon = a;
-			acceptables[2].is_dtor = true;
-
-			int ret = waitfor_internal( acceptables, swagl() );
-
-			switch( ret ) {
-				case 0:
-				{
-					bar();
-				}
-				case 1:
-				{
-					baz();
-				}
-				case 2:
-					signal(a);
-					{
-						break;
-					}
-			}
-		}
-	}
-}*/
-
-namespace Concurrency {
-	//=============================================================================================
-	// Pass declarations
-	//=============================================================================================
-
-	class GenerateWaitForPass final : public WithIndexer {
-	  public:
-
-		void premutate( FunctionDecl * decl );
-		void premutate( StructDecl   * decl );
-
-		Statement * postmutate( WaitForStmt * stmt );
-
-		static void generate( std::list< Declaration * > & translationUnit ) {
-			PassVisitor< GenerateWaitForPass > impl;
-			acceptAll( translationUnit, impl );
-		}
-
-		ObjectDecl * declare( unsigned long count, CompoundStmt * stmt );
-		ObjectDecl * declareFlag( CompoundStmt * stmt );
-		Statement  * makeSetter( ObjectDecl * flag );
-		ObjectDecl * declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt );
-		void         init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * settter, CompoundStmt * stmt );
-		Expression * init_timeout( Expression *& time, Expression *& time_cond, bool has_else, Expression *& else_cond, Statement * settter, CompoundStmt * stmt );
-		Expression * call(size_t count, ObjectDecl * acceptables, Expression * timeout, CompoundStmt * stmt);
-		void         choose( WaitForStmt * waitfor, Expression  * result, CompoundStmt * stmt );
-
-		static void implement( std::list< Declaration * > & translationUnit ) {
-			PassVisitor< GenerateWaitForPass > impl;
-			mutateAll( translationUnit, impl );
-		}
-
-
-	  private:
-	  	FunctionDecl        * decl_waitfor    = nullptr;
-	  	StructDecl          * decl_mask       = nullptr;
-		StructDecl          * decl_acceptable = nullptr;
-		StructDecl          * decl_monitor    = nullptr;
-
-		static std::unique_ptr< Type > generic_func;
-
-		UniqueName namer_acc = "__acceptables_"s;
-		UniqueName namer_idx = "__index_"s;
-		UniqueName namer_flg = "__do_run_"s;
-		UniqueName namer_msk = "__mask_"s;
-		UniqueName namer_mon = "__monitors_"s;
-		UniqueName namer_tim = "__timeout_"s;
-	};
-
-	//=============================================================================================
-	// General entry routine
-	//=============================================================================================
-	void generateWaitFor( std::list< Declaration * > & translationUnit ) {
-		GenerateWaitForPass	::implement( translationUnit );
-	}
-
-	//=============================================================================================
-	// Generic helper routine
-	//=============================================================================================
-
-	namespace {
-		Expression * makeOpIndex( DeclarationWithType * array, unsigned long index ) {
-			return new UntypedExpr(
-				new NameExpr( "?[?]" ),
-				{
-					new VariableExpr( array ),
-					new ConstantExpr( Constant::from_ulong( index ) )
-				}
-			);
-		}
-
-		Expression * makeOpAssign( Expression * lhs, Expression * rhs ) {
-			return new UntypedExpr(
-					new NameExpr( "?=?" ),
-					{ lhs, rhs }
-			);
-		}
-
-		Expression * makeOpMember( Expression * sue, const std::string & mem ) {
-			return new UntypedMemberExpr( new NameExpr( mem ), sue );
-		}
-
-		Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, const std::string & member, Expression * value, const SymTab::Indexer & indexer ) {
-			Expression * expr = makeOpAssign(
-				makeOpMember(
-					makeOpIndex(
-						object,
-						index
-					),
-					member
-				),
-				value
-			);
-
-			ResolvExpr::findVoidExpression( expr, indexer );
-
-			return new ExprStmt( expr );
-		}
-
-		Expression * safeCond( Expression * expr, bool ifnull = true ) {
-			if( expr ) return expr;
-
-			return new ConstantExpr( Constant::from_bool( ifnull ) );
-		}
-
-		VariableExpr * extractVariable( Expression * func ) {
-			if( VariableExpr * var = dynamic_cast< VariableExpr * >( func ) ) {
-				return var;
-			}
-
-			CastExpr * cast = strict_dynamic_cast< CastExpr * >( func );
-			return strict_dynamic_cast< VariableExpr * >( cast->arg );
-		}
-
-		Expression * detectIsDtor( Expression * func ) {
-			VariableExpr * typed_func = extractVariable( func );
-			bool is_dtor = InitTweak::isDestructor( typed_func->var );
-			return new ConstantExpr( Constant::from_bool( is_dtor ) );
-		}
-	};
-
-
-	//=============================================================================================
-	// Generate waitfor implementation
-	//=============================================================================================
-
-	void GenerateWaitForPass::premutate( FunctionDecl * decl) {
-		if( decl->name != "__waitfor_internal" ) return;
-
-		decl_waitfor = decl;
-	}
-
-	void GenerateWaitForPass::premutate( StructDecl   * decl ) {
-		if( ! decl->body ) return;
-
-		if( decl->name == "__acceptable_t" ) {
-			assert( !decl_acceptable );
-			decl_acceptable = decl;
-		}
-		else if( decl->name == "__waitfor_mask_t" ) {
-			assert( !decl_mask );
-			decl_mask = decl;
-		}
-		else if( decl->name == "monitor$" ) {
-			assert( !decl_monitor );
-			decl_monitor = decl;
-		}
-	}
-
-	Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
-		if( !decl_monitor || !decl_acceptable || !decl_mask )
-			SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor.hfa>" );
-
-		CompoundStmt * stmt = new CompoundStmt();
-
-		ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
-		ObjectDecl * flag        = declareFlag( stmt );
-		Statement  * setter      = makeSetter( flag );
-
-		int index = 0;
-		for( auto & clause : waitfor->clauses ) {
-			init( acceptables, index, clause, setter, stmt );
-
-			index++;
-		}
-
-		Expression * timeout = init_timeout(
-			waitfor->timeout.time,
-			waitfor->timeout.condition,
-			waitfor->orelse .statement,
-			waitfor->orelse .condition,
-			setter,
-			stmt
-		);
-
-		CompoundStmt * compound = new CompoundStmt();
-		stmt->push_back( new IfStmt(
-			safeCond( new VariableExpr( flag ) ),
-			compound,
-			nullptr
-		));
-
-		Expression * result = call( waitfor->clauses.size(), acceptables, timeout, compound );
-
-		choose( waitfor, result, compound );
-
-		return stmt;
-	}
-
-	ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
-	{
-		ObjectDecl * acceptables = ObjectDecl::newObject(
-			namer_acc.newName(),
-			new ArrayType(
-				noQualifiers,
-				new StructInstType(
-					noQualifiers,
-					decl_acceptable
-				),
-				new ConstantExpr( Constant::from_ulong( count ) ),
-				false,
-				false
-			),
-			nullptr
-		);
-
-		stmt->push_back( new DeclStmt( acceptables) );
-
-		Expression * set = new UntypedExpr(
-			new NameExpr( "__builtin_memset" ),
-			{
-				new VariableExpr( acceptables ),
-				new ConstantExpr( Constant::from_int( 0 ) ),
-				new SizeofExpr( new VariableExpr( acceptables ) )
-			}
-		);
-
-		ResolvExpr::findVoidExpression( set, indexer );
-
-		stmt->push_back( new ExprStmt( set ) );
-
-		return acceptables;
-	}
-
-	ObjectDecl * GenerateWaitForPass::declareFlag( CompoundStmt * stmt ) {
-		ObjectDecl * flag = ObjectDecl::newObject(
-			namer_flg.newName(),
-			new BasicType(
-				noQualifiers,
-				BasicType::Bool
-			),
-			new SingleInit( new ConstantExpr( Constant::from_ulong( 0 ) ) )
-		);
-
-		stmt->push_back( new DeclStmt( flag) );
-
-		return flag;
-	}
-
-	Statement * GenerateWaitForPass::makeSetter( ObjectDecl * flag ) {
-		Expression * expr = new UntypedExpr(
-			new NameExpr( "?=?" ),
-			{
-				new VariableExpr( flag ),
-				new ConstantExpr( Constant::from_ulong( 1 ) )
-			}
-		);
-
-		ResolvExpr::findVoidExpression( expr, indexer );
-
-		return new ExprStmt( expr );
-	}
-
-	ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
-
-		ObjectDecl * mon = ObjectDecl::newObject(
-			namer_mon.newName(),
-			new ArrayType(
-				noQualifiers,
-				new PointerType(
-					noQualifiers,
-					new StructInstType(
-						noQualifiers,
-						decl_monitor
-					)
-				),
-				new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ),
-				false,
-				false
-			),
-			new ListInit(
-				map_range < std::list<Initializer*> > ( clause.target.arguments, [](Expression * expr ){
-					return new SingleInit( expr );
-				})
-			)
-		);
-
-		stmt->push_back( new DeclStmt( mon) );
-
-		return mon;
-	}
-
-	void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * setter, CompoundStmt * stmt ) {
-
-		ObjectDecl * monitors = declMon( clause, stmt );
-
-		Type * fptr_t = new PointerType( noQualifiers, new FunctionType( noQualifiers, true ) );
-
-		stmt->push_back( new IfStmt(
-			safeCond( clause.condition ),
-			new CompoundStmt({
-				makeAccStatement( acceptables, index, "is_dtor", detectIsDtor( clause.target.function )                                    , indexer ),
-				makeAccStatement( acceptables, index, "func"   , new CastExpr( clause.target.function, fptr_t, false )                     , indexer ),
-				makeAccStatement( acceptables, index, "data"   , new VariableExpr( monitors )                                              , indexer ),
-				makeAccStatement( acceptables, index, "size"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
-				setter->clone()
-			}),
-			nullptr
-		));
-
-		clause.target.function = nullptr;
-		clause.target.arguments.clear();
-		clause.condition = nullptr;
-	}
-
-	Expression * GenerateWaitForPass::init_timeout(
-		Expression *& time,
-		Expression *& time_cond,
-		bool has_else,
-		Expression *& else_cond,
-		Statement * setter,
-		CompoundStmt * stmt
-	) {
-		ObjectDecl * timeout = ObjectDecl::newObject(
-			namer_tim.newName(),
-			new BasicType(
-				noQualifiers,
-				BasicType::LongLongUnsignedInt
-			),
-			new SingleInit(
-				new ConstantExpr( Constant::from_int( -1 ) )
-			)
-		);
-
-		stmt->push_back( new DeclStmt( timeout ) );
-
-		if( time ) {
-			stmt->push_back( new IfStmt(
-				safeCond( time_cond ),
-				new CompoundStmt({
-					new ExprStmt(
-						makeOpAssign(
-							new VariableExpr( timeout ),
-							time
-						)
-					),
-					setter->clone()
-				}),
-				nullptr
-			));
-
-			time = time_cond = nullptr;
-		}
-
-		if( has_else ) {
-			stmt->push_back( new IfStmt(
-				safeCond( else_cond ),
-				new CompoundStmt({
-					new ExprStmt(
-						makeOpAssign(
-							new VariableExpr( timeout ),
-							new ConstantExpr( Constant::from_ulong( 0 ) )
-						)
-					),
-					setter->clone()
-				}),
-				nullptr
-			));
-
-			else_cond = nullptr;
-		}
-
-		delete setter;
-
-		return new VariableExpr( timeout );
-	}
-
-	Expression * GenerateWaitForPass::call(
-		size_t count,
-		ObjectDecl * acceptables,
-		Expression * timeout,
-		CompoundStmt * stmt
-	) {
-		ObjectDecl * index = ObjectDecl::newObject(
-			namer_idx.newName(),
-			new BasicType(
-				noQualifiers,
-				BasicType::ShortSignedInt
-			),
-			new SingleInit(
-				new ConstantExpr( Constant::from_int( -1 ) )
-			)
-		);
-
-		stmt->push_back( new DeclStmt( index ) );
-
-		ObjectDecl * mask = ObjectDecl::newObject(
-			namer_msk.newName(),
-			new StructInstType(
-				noQualifiers,
-				decl_mask
-			),
-			new ListInit({
-				new SingleInit( new AddressExpr( new VariableExpr( index ) ) ),
-				new ListInit({
-					new SingleInit( new VariableExpr( acceptables ) ),
-					new SingleInit( new ConstantExpr( Constant::from_ulong( count ) ) )
-				})
-			})
-		);
-
-		stmt->push_back( new DeclStmt( mask ) );
-
-		stmt->push_back( new ExprStmt(
-			new ApplicationExpr(
-				VariableExpr::functionPointer( decl_waitfor ),
-				{
-					new CastExpr(
-						new VariableExpr( mask ),
-						new ReferenceType(
-							noQualifiers,
-							new StructInstType(
-								noQualifiers,
-								decl_mask
-							)
-						),
-						false
-					),
-					timeout
-				}
-			)
-		));
-
-		return new VariableExpr( index );
-	}
-
-	void GenerateWaitForPass::choose(
-		WaitForStmt * waitfor,
-		Expression  * result,
-		CompoundStmt * stmt
-	) {
-		SwitchStmt * swtch = new SwitchStmt(
-			result,
-			std::list<Statement *>()
-		);
-
-		unsigned long i = 0;
-		for( auto & clause : waitfor->clauses ) {
-			swtch->statements.push_back(
-				new CaseStmt(
-					new ConstantExpr( Constant::from_ulong( i++ ) ),
-					{
-						new CompoundStmt({
-							clause.statement,
-							new BranchStmt(
-								"",
-								BranchStmt::Break
-							)
-						})
-					}
-				)
-			);
-		}
-
-		if(waitfor->timeout.statement) {
-			swtch->statements.push_back(
-				new CaseStmt(
-					new ConstantExpr( Constant::from_int( -2 ) ),
-					{
-						new CompoundStmt({
-							waitfor->timeout.statement,
-							new BranchStmt(
-								"",
-								BranchStmt::Break
-							)
-						})
-					}
-				)
-			);
-		}
-
-		if(waitfor->orelse.statement) {
-			swtch->statements.push_back(
-				new CaseStmt(
-					new ConstantExpr( Constant::from_int( -1 ) ),
-					{
-						new CompoundStmt({
-							waitfor->orelse.statement,
-							new BranchStmt(
-								"",
-								BranchStmt::Break
-							)
-						})
-					}
-				)
-			);
-		}
-
-		stmt->push_back( swtch );
-	}
-};
-
-// Local Variables: //
-// mode: c //
-// tab-width: 4 //
-// End: //
Index: src/Concurrency/module.mk
===================================================================
--- src/Concurrency/module.mk	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Concurrency/module.mk	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -21,8 +21,6 @@
 	Concurrency/Corun.hpp \
 	Concurrency/KeywordsNew.cpp \
-	Concurrency/Keywords.cc \
 	Concurrency/Keywords.h \
 	Concurrency/WaitforNew.cpp \
-	Concurrency/Waitfor.cc \
 	Concurrency/Waitfor.h \
 	Concurrency/Waituntil.cpp \
Index: c/ControlStruct/ExceptDecl.cc
===================================================================
--- src/ControlStruct/ExceptDecl.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,482 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// ExceptDecl.cc -- Handles declarations of exception types.
-//
-// Author           : Henry Xue
-// Created On       : Tue Jul 20 04:10:50 2021
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed May 25 16:43:00 2022
-// Update Count     : 5
-//
-
-#include "ExceptDecl.h"
-
-#include <cassert>               // for assert
-#include <string>                // for string
-#include <sstream>               // for stringstream
-
-#include "Common/PassVisitor.h"  // for PassVisitor
-#include "Common/utility.h"      // for cloneAll
-#include "SynTree/Mutator.h"     // for mutateAll
-#include "Virtual/Tables.h"      // for helpers
-
-namespace ControlStruct {
-
-const std::list< Expression *> & makeParameters(
-	const std::list< TypeDecl *> & forallClause
-) {
-	auto parameters = new std::list< Expression *>();
-	for ( auto it = forallClause.begin(); it != forallClause.end(); it++ ) {
-		parameters->emplace_back( new TypeExpr(
-			new TypeInstType( noQualifiers, ( *it )->get_name(), false )
-		) );
-	}
-	return *parameters;
-}
-
-StructInstType * makeExceptInstType(
-	const std::string & exceptionName,
-	const std::list< Expression *> & parameters
-) {
-	StructInstType * exceptInstType = new StructInstType(
-		noQualifiers,
-		exceptionName
-	);
-	cloneAll( parameters, exceptInstType->parameters );
-	return exceptInstType;
-}
-
-// void (*copy)(exception_name parameters * this, exception_name parameters * that);
-FunctionType * makeCopyFnType(
-	const std::string & exceptionName,
-	const std::list< Expression *> & parameters
-) {
-	FunctionType * copyFnType = new FunctionType( noQualifiers, false );
-	copyFnType->get_parameters().push_back( new ObjectDecl(
-		"this",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new PointerType( noQualifiers,
-			makeExceptInstType( exceptionName, parameters ) ),
-		nullptr
-	) );
-	copyFnType->get_parameters().push_back( new ObjectDecl(
-		"that",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new PointerType( noQualifiers,
-			makeExceptInstType( exceptionName, parameters ) ),
-		nullptr
-	) );
-	copyFnType->get_returnVals().push_back( new ObjectDecl(
-		"",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new VoidType( noQualifiers ),
-		nullptr
-	) );
-	return copyFnType;
-}
-
-// void (*^?{})(exception_name parameters & this);
-FunctionType * makeDtorFnType(
-	const std::string & exceptionName,
-	const std::list< Expression *> & parameters
-) {
-	FunctionType * dtorFnType = new FunctionType( noQualifiers, false );
-	dtorFnType->get_parameters().push_back( new ObjectDecl(
-		"this",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new ReferenceType( noQualifiers,
-			makeExceptInstType( exceptionName, parameters ) ),
-		nullptr
-	) );
-	dtorFnType->get_returnVals().push_back( new ObjectDecl(
-		"",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new VoidType( noQualifiers ),
-		nullptr
-	) );
-	return dtorFnType;
-}
-
-// const char * (*msg)(exception_name parameters * this);
-FunctionType * makeMsgFnType(
-	const std::string & exceptionName,
-	const std::list< Expression *> & parameters
-) {
-	FunctionType * msgFnType = new FunctionType( noQualifiers, false );
-	msgFnType->get_parameters().push_back( new ObjectDecl(
-		"this",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new PointerType( noQualifiers,
-			makeExceptInstType( exceptionName, parameters ) ),
-		nullptr
-	) );
-	msgFnType->get_returnVals().push_back( new ObjectDecl(
-		"",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new PointerType( noQualifiers,
-			new BasicType( Type::Const, BasicType::Char ) ),
-		nullptr
-	) );
-	return msgFnType;
-}
-
-StructDecl * ehmTypeIdStruct(
-	const std::string & exceptionName,
-	const std::list< TypeDecl *> & forallClause
-) {
-	StructDecl * structDecl = new StructDecl( Virtual::typeIdType( exceptionName ) );
-	structDecl->members.push_back( new ObjectDecl(
-		"parent",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new PointerType( noQualifiers,
-			new StructInstType( Type::Const, "__cfavir_type_info" ) ),
-		nullptr
-	) );
-	structDecl->set_body( true );
-	cloneAll( forallClause, structDecl->parameters );
-	return structDecl;
-}
-
-ObjectDecl * ehmTypeIdValue(
-	const std::string & exceptionName,
-	const std::list< Expression *> & parameters
-) {
-	StructInstType * typeIdType = new StructInstType(
-		Type::Const,
-		Virtual::typeIdType( exceptionName )
-	);
-	cloneAll( parameters, typeIdType->parameters );
-	return new ObjectDecl(
-		Virtual::typeIdName( exceptionName ),
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		typeIdType,
-		new ListInit( { new SingleInit(
-			new AddressExpr( new NameExpr( "__cfatid_exception_t" ) )
-			) }, {}, true ),
-		{ new Attribute( "cfa_linkonce" ) }
-	);
-}
-
-StructDecl * ehmExceptionStructDecl(
-	const std::string & exceptionName,
-	const std::list< TypeDecl *> & forallClause
-) {
-	StructDecl * structDecl = new StructDecl( exceptionName );
-	cloneAll( forallClause, structDecl->parameters );
-	return structDecl;
-}
-
-StructDecl * ehmVirtualTableStruct(
-	const std::string & exceptionName,
-	const std::list< TypeDecl *> & forallClause,
-	const std::list< Expression *> & parameters
-) {
-	StructInstType * typeIdType = new StructInstType(
-		Type::Const,
-		Virtual::typeIdType( exceptionName )
-	);
-	cloneAll( parameters, typeIdType->parameters );
-	ObjectDecl * typeId = new ObjectDecl(
-		"__cfavir_typeid",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new PointerType( noQualifiers, typeIdType ),
-		nullptr
-	);
-	ObjectDecl * size = new ObjectDecl(
-		"size",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new TypeInstType( noQualifiers, "size_t", false ),
-		nullptr
-	);
-	ObjectDecl * copy = new ObjectDecl(
-		"copy",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new PointerType( noQualifiers,
-			makeCopyFnType( exceptionName, parameters ) ),
-		nullptr
-	);
-	ObjectDecl * dtor = new ObjectDecl(
-		"^?{}",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new PointerType( noQualifiers,
-			makeDtorFnType( exceptionName, parameters ) ),
-		nullptr
-	);
-	ObjectDecl * msg = new ObjectDecl(
-		"msg",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new PointerType( noQualifiers,
-			makeMsgFnType( exceptionName, parameters ) ),
-		nullptr
-	);
-	StructDecl * structDecl = new StructDecl( Virtual::vtableTypeName( exceptionName ) );
-	structDecl->members.push_back( typeId );
-	structDecl->members.push_back( size );
-	structDecl->members.push_back( copy );
-	structDecl->members.push_back( dtor );
-	structDecl->members.push_back( msg );
-	structDecl->set_body( true );
-	cloneAll( forallClause, structDecl->parameters );
-	return structDecl;
-}
-
-StructDecl * ehmExceptionStruct(
-	const std::string & exceptionName,
-	const std::list< TypeDecl *> & forallClause,
-	const std::list< Expression *> & parameters,
-	const std::list< Declaration *> & members
-) {
-	StructInstType * vtableType = new StructInstType(
-		Type::Const,
-		Virtual::vtableTypeName( exceptionName )
-	);
-	cloneAll( parameters, vtableType->parameters );
-	StructDecl * structDecl = new StructDecl( exceptionName );
-	structDecl->members = members;
-	structDecl->members.push_front( new ObjectDecl(
-		"virtual_table",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new PointerType( noQualifiers, vtableType ),
-		nullptr
-	) );
-	structDecl->set_body( true );
-	cloneAll( forallClause, structDecl->parameters );
-	return structDecl;
-}
-
-ObjectDecl * ehmTypeIdExtern(
-	const std::string & exceptionName,
-	const std::list< Expression *> & parameters
-) {
-	StructInstType * typeIdType = new StructInstType(
-		Type::Const,
-		Virtual::typeIdType( exceptionName )
-	);
-	cloneAll( parameters, typeIdType->parameters );
-	return new ObjectDecl(
-		Virtual::typeIdName( exceptionName ),
-		Type::Extern,
-		LinkageSpec::Cforall,
-		nullptr,
-		typeIdType,
-		nullptr,
-		{ new Attribute( "cfa_linkonce" ) }
-	);
-}
-
-ObjectDecl * ehmExternVtable(
-	const std::string & exceptionName,
-	const std::list< Expression *> & parameters,
-	const std::string & tableName
-) {
-	StructInstType * vtableType = new StructInstType(
-		Type::Const,
-		Virtual::vtableTypeName( exceptionName )
-	);
-	cloneAll( parameters, vtableType->parameters );
-	return new ObjectDecl(
-		tableName,
-		Type::Extern,
-		LinkageSpec::Cforall,
-		nullptr,
-		vtableType,
-		nullptr
-	);
-}
-
-FunctionDecl * ehmDefineCopy(
-	const std::string & exceptionName,
-	const std::list< Expression *> & parameters
-) {
-	return new FunctionDecl(
-		"copy",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		makeCopyFnType( exceptionName, parameters ),
-		new CompoundStmt( {
-			new ExprStmt( new UntypedExpr( new NameExpr( "?=?" ), {
-				new UntypedExpr( new NameExpr( "*?" ), { new NameExpr( "this" ) } ),
-				new UntypedExpr( new NameExpr( "*?" ), { new NameExpr( "that" ) } )
-			} ) )
-		} )
-	);
-}
-
-FunctionDecl * ehmDefineMsg(
-	const std::string & exceptionName,
-	const std::list< Expression *> & parameters
-) {
-	std::stringstream msg;
-	msg << exceptionName;
-	if ( !parameters.empty() ) { // forall variant, add parameters
-		msg << "(";
-		for ( auto it = parameters.begin(); it != parameters.end(); it++ ) {
-			( *it )->print( msg );
-			if ( it + 1 == parameters.end() ) {
-				msg << ")"; // end of list, close bracket
-			} else {
-				msg << ", "; // otherwise use comma as separator
-			}
-		}
-	}
-	return new FunctionDecl(
-		"msg",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		makeMsgFnType( exceptionName, parameters ),
-		new CompoundStmt( {
-			new ReturnStmt( new ConstantExpr( Constant::from_string( msg.str() ) ) )
-		} )
-	);
-}
-
-ObjectDecl * ehmVirtualTable(
-	const std::string & exceptionName,
-	const std::list< Expression *> & parameters,
-	const std::string & tableName
-) {
-	StructInstType * sizeofType = new StructInstType( noQualifiers, exceptionName );
-	cloneAll( parameters, sizeofType->parameters );
-	std::list< Initializer *> inits {
-		new SingleInit( new AddressExpr(
-			new NameExpr( Virtual::typeIdName( exceptionName ) ) ) ),
-		new SingleInit( new SizeofExpr( sizeofType ) ),
-		new SingleInit( new NameExpr( "copy" ) ),
-		new SingleInit( new NameExpr( "^?{}" ) ),
-		new SingleInit( new NameExpr( "msg" ) )
-	};
-	std::list< Designation *> desig {
-		new Designation( { new NameExpr( "__cfavir_typeid" ) } ),
-		new Designation( { new NameExpr( "size" ) } ),
-		new Designation( { new NameExpr( "copy" ) } ),
-		new Designation( { new NameExpr( "^?{}" ) } ),
-		new Designation( { new NameExpr( "msg" ) } )
-	};
-	StructInstType * vtableType = new StructInstType(
-		Type::Const,
-		Virtual::vtableTypeName( exceptionName )
-	);
-	cloneAll( parameters, vtableType->parameters );
-	return new ObjectDecl(
-		tableName,
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		vtableType,
-		new ListInit( inits, desig )
-	);
-}
-
-class ExceptDeclCore : public WithDeclsToAdd {
-public:
-	// translates exception decls
-	Declaration * postmutate( StructDecl * structDecl );
-
-	// translates vtable decls
-	DeclarationWithType * postmutate( ObjectDecl * objectDecl );
-};
-
-Declaration * ExceptDeclCore::postmutate( StructDecl * structDecl ) {
-	if ( structDecl->is_exception() ) {
-		const std::string & exceptionName = structDecl->get_name();
-		const std::list< TypeDecl *> & forallClause = structDecl->get_parameters();
-		const std::list< Expression *> & parameters = makeParameters( forallClause );
-		const std::list< Declaration *> & members = structDecl->get_members();
-
-		declsToAddBefore.push_back( ehmTypeIdStruct( exceptionName, forallClause ) );
-		if ( forallClause.empty() ) { // non-forall variant
-			declsToAddBefore.push_back( ehmTypeIdValue( exceptionName, parameters ) );
-		}
-		declsToAddBefore.push_back( ehmExceptionStructDecl( exceptionName, forallClause ) );
-		declsToAddBefore.push_back( ehmVirtualTableStruct( exceptionName, forallClause, parameters ) );
-		return ehmExceptionStruct( exceptionName, forallClause, parameters, members );
-	}
-	return structDecl;
-}
-
-DeclarationWithType * ExceptDeclCore::postmutate( ObjectDecl * objectDecl ) {
-	// Check if it is VTableType
-	VTableType * vtableType = dynamic_cast< VTableType *>( objectDecl->get_type() );
-	if ( vtableType ) {
-		TypeInstType * base = dynamic_cast< TypeInstType *>( vtableType->get_base() );
-		assert( base ); // should be a TypeInstType
-		const std::string & exceptionName = base->get_name();
-		const std::string & tableName = objectDecl->get_name();
-		const std::list< Expression *> parameters = base->get_parameters();
-
-		if ( objectDecl->get_storageClasses().is_extern ) { // if extern
-			if ( !parameters.empty() ) { // forall variant
-				declsToAddBefore.push_back( ehmTypeIdExtern( exceptionName, parameters ) );
-			}
-			return ehmExternVtable( exceptionName, parameters, tableName );
-		}
-		// else, non-extern
-		if ( !parameters.empty() ) { // forall variant
-			declsToAddBefore.push_back( ehmTypeIdValue( exceptionName, parameters ) );
-		}
-		declsToAddBefore.push_back( ehmDefineCopy( exceptionName, parameters ) );
-		declsToAddBefore.push_back( ehmDefineMsg( exceptionName, parameters ) );
-		return ehmVirtualTable( exceptionName, parameters, tableName );
-	}
-	return objectDecl;
-}
-
-class VTableCore : public WithDeclsToAdd {
-public:
-	// Remove any remaining vtable type nodes in the tree.
-	Type * postmutate( VTableType * vtableType );
-};
-
-Type * VTableCore::postmutate( VTableType * vtableType ) {
-	auto inst = strict_dynamic_cast<ReferenceToType *>( vtableType->base );
-
-	std::string vtableName = Virtual::vtableTypeName( inst->name );
-	StructInstType * newType = new StructInstType( noQualifiers, vtableName );
-	cloneAll( inst->parameters, newType->parameters );
-
-	delete vtableType;
-	return newType;
-}
-
-void translateExcept( std::list< Declaration *> & translationUnit ) {
-	PassVisitor<ExceptDeclCore> translator;
-	mutateAll( translationUnit, translator );
-	PassVisitor<VTableCore> typeTranslator;
-	mutateAll( translationUnit, typeTranslator );
-}
-
-}
Index: c/ControlStruct/ExceptTranslate.cc
===================================================================
--- src/ControlStruct/ExceptTranslate.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,689 +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.
-//
-// ExceptTranslate.cc -- Conversion of exception control flow structures.
-//
-// Author           : Andrew Beach
-// Created On       : Wed Jun 14 16:49:00 2017
-// Last Modified By : Henry Xue
-// Last Modified On : Tue Aug 03 10:05:51 2021
-// Update Count     : 18
-//
-
-#include "ExceptTranslate.h"
-
-#include <stddef.h>                   // for NULL
-#include <cassert>                    // for assert, assertf
-#include <iterator>                   // for back_inserter, inserter
-#include <string>                     // for string, operator==
-
-#include "Common/PassVisitor.h"       // for PassVisitor, WithGuards
-#include "Common/SemanticError.h"     // for SemanticError
-#include "Common/utility.h"           // for CodeLocation
-#include "SynTree/LinkageSpec.h"      // for Cforall
-#include "SynTree/Attribute.h"        // for Attribute
-#include "SynTree/Constant.h"         // for Constant
-#include "SynTree/Declaration.h"      // for ObjectDecl, FunctionDecl, Struc...
-#include "SynTree/Expression.h"       // for UntypedExpr, ConstantExpr, Name...
-#include "SynTree/Initializer.h"      // for SingleInit, ListInit
-#include "SynTree/Label.h"            // for Label
-#include "SynTree/Mutator.h"          // for mutateAll
-#include "SynTree/Statement.h"        // for CompoundStmt, CatchStmt, ThrowStmt
-#include "SynTree/Type.h"             // for FunctionType, Type, noQualifiers
-#include "SynTree/DeclReplacer.h"     // for DeclReplacer
-#include "SynTree/Visitor.h"          // for acceptAll
-
-namespace ControlStruct {
-
-	// Buricratic Helpers (Not having to do with the paritular operation.)
-
-	typedef std::list<CatchStmt*> CatchList;
-
-	void split( CatchList& allHandlers, CatchList& terHandlers,
-				CatchList& resHandlers ) {
-		while ( !allHandlers.empty() ) {
-			CatchStmt * stmt = allHandlers.front();
-			allHandlers.pop_front();
-			if (CatchStmt::Terminate == stmt->get_kind()) {
-				terHandlers.push_back(stmt);
-			} else {
-				resHandlers.push_back(stmt);
-			}
-		}
-	}
-
-	void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
-		block->push_back(new DeclStmt(item));
-	}
-
-	Expression * nameOf( DeclarationWithType * decl ) {
-		return new VariableExpr( decl );
-	}
-
-	class ThrowMutatorCore : public WithGuards {
-		ObjectDecl * terminate_handler_except;
-		enum Context { NoHandler, TerHandler, ResHandler } cur_context;
-
-		// The helper functions for code/syntree generation.
-		Statement * create_either_throw(
-			ThrowStmt * throwStmt, const char * throwFunc );
-		Statement * create_terminate_rethrow( ThrowStmt * throwStmt );
-
-	public:
-		ThrowMutatorCore() :
-			terminate_handler_except( nullptr ),
-			cur_context( NoHandler )
-		{}
-
-		void premutate( CatchStmt *catchStmt );
-		Statement * postmutate( ThrowStmt *throwStmt );
-	};
-
-	// ThrowStmt Mutation Helpers
-
-	Statement * ThrowMutatorCore::create_either_throw(
-			ThrowStmt * throwStmt, const char * throwFunc ) {
-		// `throwFunc`( `throwStmt->get_name()` );
-		UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
-		call->get_args().push_back( throwStmt->get_expr() );
-		throwStmt->set_expr( nullptr );
-		delete throwStmt;
-		return new ExprStmt( call );
-	}
-
-	Statement * ThrowMutatorCore::create_terminate_rethrow(
-			ThrowStmt *throwStmt ) {
-		// { `terminate_handler_except` = 0p; __rethrow_terminate(); }
-		assert( nullptr == throwStmt->get_expr() );
-		assert( terminate_handler_except );
-
-		CompoundStmt * result = new CompoundStmt();
-		result->labels =  throwStmt->labels;
-		result->push_back( new ExprStmt( UntypedExpr::createAssign(
-			nameOf( terminate_handler_except ),
-			new ConstantExpr( Constant::null(
-				terminate_handler_except->get_type()->clone()
-				) )
-			) ) );
-		result->push_back( new ExprStmt(
-			new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) )
-			) );
-		delete throwStmt;
-		return result;
-	}
-
-	// Visiting/Mutating Functions
-
-	void ThrowMutatorCore::premutate( CatchStmt *catchStmt ) {
-		// Validate the statement's form.
-		ObjectDecl * decl = dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
-		// Also checking the type would be nice.
-		if ( !decl || !dynamic_cast<PointerType *>( decl->type ) ) {
-			std::string kind = (CatchStmt::Terminate == catchStmt->kind) ? "catch" : "catchResume";
-			SemanticError( catchStmt->location, kind + " must have pointer to an exception type" );
-		}
-
-		// Track the handler context.
-		GuardValue( cur_context );
-		if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
-			cur_context = TerHandler;
-
-			GuardValue( terminate_handler_except );
-			terminate_handler_except = decl;
-		} else {
-			cur_context = ResHandler;
-		}
-	}
-
-	Statement * ThrowMutatorCore::postmutate( ThrowStmt *throwStmt ) {
-		// Ignoring throwStmt->get_target() for now.
-		if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
-			if ( throwStmt->get_expr() ) {
-				return create_either_throw( throwStmt, "$throw" );
-			} else if ( TerHandler == cur_context ) {
-				return create_terminate_rethrow( throwStmt );
-			} else {
-				abort("Invalid throw in %s at %i\n",
-					throwStmt->location.filename.c_str(),
-					throwStmt->location.first_line);
-			}
-		} else {
-			if ( throwStmt->get_expr() ) {
-				return create_either_throw( throwStmt, "$throwResume" );
-			} else if ( ResHandler == cur_context ) {
-				// This has to be handled later.
-				return throwStmt;
-			} else {
-				abort("Invalid throwResume in %s at %i\n",
-					throwStmt->location.filename.c_str(),
-					throwStmt->location.first_line);
-			}
-		}
-	}
-
-	class TryMutatorCore {
-		// The built in types used in translation.
-		StructDecl * except_decl;
-		StructDecl * node_decl;
-		StructDecl * hook_decl;
-
-		// The many helper functions for code/syntree generation.
-		CompoundStmt * take_try_block( TryStmt * tryStmt );
-		FunctionDecl * create_try_wrapper( CompoundStmt * body );
-		FunctionDecl * create_terminate_catch( CatchList &handlers );
-		CompoundStmt * create_single_matcher(
-			DeclarationWithType * except_obj, CatchStmt * modded_handler );
-		FunctionDecl * create_terminate_match( CatchList &handlers );
-		CompoundStmt * create_terminate_caller( FunctionDecl * try_wrapper,
-			FunctionDecl * terminate_catch, FunctionDecl * terminate_match );
-		FunctionDecl * create_resume_handler( CatchList &handlers );
-		CompoundStmt * create_resume_wrapper(
-			Statement * wraps, FunctionDecl * resume_handler );
-		FunctionDecl * create_finally_wrapper( TryStmt * tryStmt );
-		ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper );
-		Statement * create_resume_rethrow( ThrowStmt * throwStmt );
-
-		// Types used in translation, make sure to use clone.
-		// void (*function)();
-		FunctionType try_func_t;
-		// void (*function)(int, exception);
-		FunctionType catch_func_t;
-		// int (*function)(exception);
-		FunctionType match_func_t;
-		// bool (*function)(exception);
-		FunctionType handle_func_t;
-		// void (*function)(__attribute__((unused)) void *);
-		FunctionType finally_func_t;
-
-		StructInstType * create_except_type() {
-			assert( except_decl );
-			return new StructInstType( noQualifiers, except_decl );
-		}
-		void init_func_types();
-
-	public:
-		TryMutatorCore() :
-			except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ),
-			try_func_t( noQualifiers, false ),
-			catch_func_t( noQualifiers, false ),
-			match_func_t( noQualifiers, false ),
-			handle_func_t( noQualifiers, false ),
-			finally_func_t( noQualifiers, false )
-		{}
-
-		void premutate( StructDecl *structDecl );
-		Statement * postmutate( TryStmt *tryStmt );
-		Statement * postmutate( ThrowStmt *throwStmt );
-	};
-
-	void TryMutatorCore::init_func_types() {
-		assert( except_decl );
-
-		ObjectDecl index_obj(
-			"__handler_index",
-			Type::StorageClasses(),
-			LinkageSpec::Cforall,
-			/*bitfieldWidth*/ NULL,
-			new BasicType( noQualifiers, BasicType::SignedInt ),
-			/*init*/ NULL
-			);
-		ObjectDecl exception_obj(
-			"__exception_inst",
-			Type::StorageClasses(),
-			LinkageSpec::Cforall,
-			/*bitfieldWidth*/ NULL,
-			new PointerType(
-				noQualifiers,
-				new StructInstType( noQualifiers, except_decl )
-				),
-			/*init*/ NULL
-			);
-		ObjectDecl bool_obj(
-			"__ret_bool",
-			Type::StorageClasses(),
-			LinkageSpec::Cforall,
-			/*bitfieldWidth*/ NULL,
-			new BasicType( noQualifiers, BasicType::Bool ),
-			/*init*/ NULL,
-			std::list<Attribute *>{ new Attribute( "unused" ) }
-			);
-		ObjectDecl voidptr_obj(
-			"__hook",
-			Type::StorageClasses(),
-			LinkageSpec::Cforall,
-			NULL,
-			new PointerType(
-				noQualifiers,
-				new VoidType(
-					noQualifiers
-					),
-				std::list<Attribute *>{ new Attribute( "unused" ) }
-				),
-			NULL
-			);
-
-		ObjectDecl * unused_index_obj = index_obj.clone();
-		unused_index_obj->attributes.push_back( new Attribute( "unused" ) );
-
-		catch_func_t.get_parameters().push_back( index_obj.clone() );
-		catch_func_t.get_parameters().push_back( exception_obj.clone() );
-		match_func_t.get_returnVals().push_back( unused_index_obj );
-		match_func_t.get_parameters().push_back( exception_obj.clone() );
-		handle_func_t.get_returnVals().push_back( bool_obj.clone() );
-		handle_func_t.get_parameters().push_back( exception_obj.clone() );
-		finally_func_t.get_parameters().push_back( voidptr_obj.clone() );
-	}
-
-	// TryStmt Mutation Helpers
-
-	CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) {
-		CompoundStmt * block = tryStmt->get_block();
-		tryStmt->set_block( nullptr );
-		return block;
-	}
-
-	FunctionDecl * TryMutatorCore::create_try_wrapper(
-			CompoundStmt *body ) {
-
-		return new FunctionDecl( "try", Type::StorageClasses(),
-			LinkageSpec::Cforall, try_func_t.clone(), body );
-	}
-
-	FunctionDecl * TryMutatorCore::create_terminate_catch(
-			CatchList &handlers ) {
-		std::list<CaseStmt *> handler_wrappers;
-
-		FunctionType *func_type = catch_func_t.clone();
-		DeclarationWithType * index_obj = func_type->get_parameters().front();
-		DeclarationWithType * except_obj = func_type->get_parameters().back();
-
-		// Index 1..{number of handlers}
-		int index = 0;
-		CatchList::iterator it = handlers.begin();
-		for ( ; it != handlers.end() ; ++it ) {
-			++index;
-			CatchStmt * handler = *it;
-
-			// case `index`:
-			// {
-			//     `handler.decl` = { (virtual `decl.type`)`except` };
-			//     `handler.body`;
-			// }
-			// return;
-			CompoundStmt * block = new CompoundStmt();
-
-			// Just copy the exception value. (Post Validation)
-			ObjectDecl * handler_decl =
-				static_cast<ObjectDecl *>( handler->get_decl() );
-			ObjectDecl * local_except = handler_decl->clone();
-			VirtualCastExpr * vcex = new VirtualCastExpr(
-				nameOf( except_obj ),
-				local_except->get_type()
-				);
-			vcex->location = handler->location;
-			local_except->set_init( new ListInit({ new SingleInit( vcex ) }) );
-			block->push_back( new DeclStmt( local_except ) );
-
-			// Add the cleanup attribute.
-			local_except->get_attributes().push_back( new Attribute(
-				"cleanup",
-				{ new NameExpr( "__cfaehm_cleanup_terminate" ) }
-				) );
-
-			// Update variables in the body to point to this local copy.
-			{
-				DeclReplacer::DeclMap mapping;
-				mapping[ handler_decl ] = local_except;
-				DeclReplacer::replace( handler->body, mapping );
-			}
-
-			block->push_back( handler->body );
-			handler->body = nullptr;
-
-			std::list<Statement *> caseBody
-					{ block, new ReturnStmt( nullptr ) };
-			handler_wrappers.push_back( new CaseStmt(
-				new ConstantExpr( Constant::from_int( index ) ),
-				caseBody
-				) );
-		}
-		// TODO: Some sort of meaningful error on default perhaps?
-
-		std::list<Statement*> stmt_handlers;
-		while ( !handler_wrappers.empty() ) {
-			stmt_handlers.push_back( handler_wrappers.front() );
-			handler_wrappers.pop_front();
-		}
-
-		SwitchStmt * handler_lookup = new SwitchStmt(
-			nameOf( index_obj ),
-			stmt_handlers
-			);
-		CompoundStmt * body = new CompoundStmt();
-		body->push_back( handler_lookup );
-
-		return new FunctionDecl("catch", Type::StorageClasses(),
-			LinkageSpec::Cforall, func_type, body);
-	}
-
-	// Create a single check from a moddified handler.
-	// except_obj is referenced, modded_handler will be freed.
-	CompoundStmt * TryMutatorCore::create_single_matcher(
-			DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
-		// {
-		//     `modded_handler.decl`
-		//     if ( `decl.name = (virtual `decl.type`)`except`
-		//             [&& `modded_handler.cond`] ) {
-		//         `modded_handler.body`
-		//     }
-		// }
-
-		CompoundStmt * block = new CompoundStmt();
-
-		// Local Declaration
-		ObjectDecl * local_except =
-			dynamic_cast<ObjectDecl *>( modded_handler->get_decl() );
-		assert( local_except );
-		block->push_back( new DeclStmt( local_except ) );
-
-		// Check for type match.
-		VirtualCastExpr * vcex = new VirtualCastExpr(
-			nameOf( except_obj ),
-			local_except->get_type()->clone()
-			);
-		vcex->location = modded_handler->location;
-		Expression * cond = UntypedExpr::createAssign(
-			nameOf( local_except ), vcex );
-
-		// Add the check on the conditional if it is provided.
-		if ( modded_handler->get_cond() ) {
-			cond = new LogicalExpr( cond, modded_handler->get_cond() );
-		}
-		// Construct the match condition.
-		block->push_back( new IfStmt(
-			cond, modded_handler->get_body(), nullptr ) );
-
-		modded_handler->set_decl( nullptr );
-		modded_handler->set_cond( nullptr );
-		modded_handler->set_body( nullptr );
-		delete modded_handler;
-		return block;
-	}
-
-	FunctionDecl * TryMutatorCore::create_terminate_match(
-			CatchList &handlers ) {
-		// int match(exception * except) {
-		//     HANDLER WRAPPERS { return `index`; }
-		// }
-
-		CompoundStmt * body = new CompoundStmt();
-
-		FunctionType * func_type = match_func_t.clone();
-		DeclarationWithType * except_obj = func_type->get_parameters().back();
-
-		// Index 1..{number of handlers}
-		int index = 0;
-		CatchList::iterator it;
-		for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
-			++index;
-			CatchStmt * handler = *it;
-
-			// Body should have been taken by create_terminate_catch.
-			assert( nullptr == handler->get_body() );
-
-			// Create new body.
-			handler->set_body( new ReturnStmt(
-				new ConstantExpr( Constant::from_int( index ) ) ) );
-
-			// Create the handler.
-			body->push_back( create_single_matcher( except_obj, handler ) );
-			*it = nullptr;
-		}
-
-		body->push_back( new ReturnStmt(
-			new ConstantExpr( Constant::from_int( 0 ) ) ) );
-
-		return new FunctionDecl("match", Type::StorageClasses(),
-			LinkageSpec::Cforall, func_type, body);
-	}
-
-	CompoundStmt * TryMutatorCore::create_terminate_caller(
-			FunctionDecl * try_wrapper,
-			FunctionDecl * terminate_catch,
-			FunctionDecl * terminate_match ) {
-		// { __cfaehm_try_terminate(`try`, `catch`, `match`); }
-
-		UntypedExpr * caller = new UntypedExpr( new NameExpr(
-			"__cfaehm_try_terminate" ) );
-		std::list<Expression *>& args = caller->get_args();
-		args.push_back( nameOf( try_wrapper ) );
-		args.push_back( nameOf( terminate_catch ) );
-		args.push_back( nameOf( terminate_match ) );
-
-		CompoundStmt * callStmt = new CompoundStmt();
-		callStmt->push_back( new ExprStmt( caller ) );
-		return callStmt;
-	}
-
-	FunctionDecl * TryMutatorCore::create_resume_handler(
-			CatchList &handlers ) {
-		// bool handle(exception * except) {
-		//     HANDLER WRAPPERS { `hander->body`; return true; }
-		// }
-		CompoundStmt * body = new CompoundStmt();
-
-		FunctionType * func_type = handle_func_t.clone();
-		DeclarationWithType * except_obj = func_type->get_parameters().back();
-
-		CatchList::iterator it;
-		for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
-			CatchStmt * handler = *it;
-
-			// Modifiy body.
-			CompoundStmt * handling_code =
-				dynamic_cast<CompoundStmt*>( handler->get_body() );
-			if ( ! handling_code ) {
-				handling_code = new CompoundStmt();
-				handling_code->push_back( handler->get_body() );
-			}
-			handling_code->push_back( new ReturnStmt(
-				new ConstantExpr( Constant::from_bool( true ) ) ) );
-			handler->set_body( handling_code );
-
-			// Create the handler.
-			body->push_back( create_single_matcher( except_obj, handler ) );
-			*it = nullptr;
-		}
-
-		body->push_back( new ReturnStmt(
-			new ConstantExpr( Constant::from_bool( false ) ) ) );
-
-		return new FunctionDecl("handle", Type::StorageClasses(),
-			LinkageSpec::Cforall, func_type, body);
-	}
-
-	CompoundStmt * TryMutatorCore::create_resume_wrapper(
-			Statement * wraps,
-			FunctionDecl * resume_handler ) {
-		CompoundStmt * body = new CompoundStmt();
-
-		// struct __try_resume_node __resume_node
-		//  	__attribute__((cleanup( __cfaehm_try_resume_cleanup )));
-		// ** unwinding of the stack here could cause problems **
-		// ** however I don't think that can happen currently **
-		// __cfaehm_try_resume_setup( &__resume_node, resume_handler );
-
-		std::list< Attribute * > attributes;
-		{
-			std::list< Expression * > attr_params;
-			attr_params.push_back( new NameExpr(
-				"__cfaehm_try_resume_cleanup" ) );
-			attributes.push_back( new Attribute( "cleanup", attr_params ) );
-		}
-
-		ObjectDecl * obj = new ObjectDecl(
-			"__resume_node",
-			Type::StorageClasses(),
-			LinkageSpec::Cforall,
-			nullptr,
-			new StructInstType(
-				Type::Qualifiers(),
-				node_decl
-				),
-			nullptr,
-			attributes
-			);
-		appendDeclStmt( body, obj );
-
-		UntypedExpr *setup = new UntypedExpr( new NameExpr(
-			"__cfaehm_try_resume_setup" ) );
-		setup->get_args().push_back( new AddressExpr( nameOf( obj ) ) );
-		setup->get_args().push_back( nameOf( resume_handler ) );
-
-		body->push_back( new ExprStmt( setup ) );
-
-		body->push_back( wraps );
-		return body;
-	}
-
-	FunctionDecl * TryMutatorCore::create_finally_wrapper(
-			TryStmt * tryStmt ) {
-		// void finally() { `finally->block` }
-		FinallyStmt * finally = tryStmt->get_finally();
-		CompoundStmt * body = finally->get_block();
-		finally->set_block( nullptr );
-		delete finally;
-		tryStmt->set_finally( nullptr );
-
-		return new FunctionDecl("finally", Type::StorageClasses(),
-			LinkageSpec::Cforall, finally_func_t.clone(), body);
-	}
-
-	ObjectDecl * TryMutatorCore::create_finally_hook(
-			FunctionDecl * finally_wrapper ) {
-		// struct __cfaehm_cleanup_hook __finally_hook
-		//   	__attribute__((cleanup( `finally_wrapper` )));
-
-		// Make Cleanup Attribute.
-		std::list< Attribute * > attributes;
-		{
-			std::list< Expression * > attr_params;
-			attr_params.push_back( nameOf( finally_wrapper ) );
-			attributes.push_back( new Attribute( "cleanup", attr_params ) );
-		}
-
-		return new ObjectDecl(
-			"__finally_hook",
-			Type::StorageClasses(),
-			LinkageSpec::Cforall,
-			nullptr,
-			new StructInstType(
-				noQualifiers,
-				hook_decl
-				),
-			nullptr,
-			attributes
-			);
-	}
-
-	Statement * TryMutatorCore::create_resume_rethrow( ThrowStmt *throwStmt ) {
-		// return false;
-		Statement * result = new ReturnStmt(
-			new ConstantExpr( Constant::from_bool( false ) )
-			);
-		result->labels = throwStmt->labels;
-		delete throwStmt;
-		return result;
-	}
-
-	// Visiting/Mutating Functions
-	void TryMutatorCore::premutate( StructDecl *structDecl ) {
-		if ( !structDecl->has_body() ) {
-			// Skip children?
-			return;
-		} else if ( structDecl->get_name() == "__cfaehm_base_exception_t" ) {
-			assert( nullptr == except_decl );
-			except_decl = structDecl;
-			init_func_types();
-		} else if ( structDecl->get_name() == "__cfaehm_try_resume_node" ) {
-			assert( nullptr == node_decl );
-			node_decl = structDecl;
-		} else if ( structDecl->get_name() == "__cfaehm_cleanup_hook" ) {
-			assert( nullptr == hook_decl );
-			hook_decl = structDecl;
-		}
-	}
-
-	Statement * TryMutatorCore::postmutate( TryStmt *tryStmt ) {
-		assert( except_decl );
-		assert( node_decl );
-		assert( hook_decl );
-
-		// Generate a prefix for the function names?
-
-		CompoundStmt * block = new CompoundStmt();
-		CompoundStmt * inner = take_try_block( tryStmt );
-
-		if ( tryStmt->get_finally() ) {
-			// Define the helper function.
-			FunctionDecl * finally_block =
-				create_finally_wrapper( tryStmt );
-			appendDeclStmt( block, finally_block );
-			// Create and add the finally cleanup hook.
-			appendDeclStmt( block, create_finally_hook( finally_block ) );
-		}
-
-		CatchList termination_handlers;
-		CatchList resumption_handlers;
-		split( tryStmt->get_catchers(),
-			   termination_handlers, resumption_handlers );
-
-		if ( resumption_handlers.size() ) {
-			// Define the helper function.
-			FunctionDecl * resume_handler =
-				create_resume_handler( resumption_handlers );
-			appendDeclStmt( block, resume_handler );
-			// Prepare hooks
-			inner = create_resume_wrapper( inner, resume_handler );
-		}
-
-		if ( termination_handlers.size() ) {
-			// Define the three helper functions.
-			FunctionDecl * try_wrapper = create_try_wrapper( inner );
-			appendDeclStmt( block, try_wrapper );
-			FunctionDecl * terminate_catch =
-				create_terminate_catch( termination_handlers );
-			appendDeclStmt( block, terminate_catch );
-			FunctionDecl * terminate_match =
-				create_terminate_match( termination_handlers );
-			appendDeclStmt( block, terminate_match );
-			// Build the call to the try wrapper.
-			inner = create_terminate_caller(
-				try_wrapper, terminate_catch, terminate_match );
-		}
-
-		// Embed the try block.
-		block->push_back( inner );
-
-		return block;
-	}
-
-	Statement * TryMutatorCore::postmutate( ThrowStmt *throwStmt ) {
-		// Only valid `throwResume;` statements should remain. (2/3 checks)
-		assert( ThrowStmt::Resume == throwStmt->kind && ! throwStmt->expr );
-		return create_resume_rethrow( throwStmt );
-	}
-
-	void translateThrows( std::list< Declaration *> & translationUnit ) {
-		PassVisitor<ThrowMutatorCore> translator;
-		mutateAll( translationUnit, translator );
-	}
-
-	void translateTries( std::list< Declaration *> & translationUnit ) {
-		PassVisitor<TryMutatorCore> translator;
-		mutateAll( translationUnit, translator );
-	}
-}
Index: c/ControlStruct/ForExprMutator.cc
===================================================================
--- src/ControlStruct/ForExprMutator.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,56 +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.
-//
-// ForExprMutator.cc --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Feb  1 09:26:12 2022
-// Update Count     : 16
-//
-
-#include <list>                 // for list, _List_iterator, list<>::iterator
-
-#include "ForExprMutator.h"
-#include "SynTree/Label.h"      // for Label
-#include "SynTree/Statement.h"  // for Statement (ptr only), ForStmt, Compou...
-
-namespace ControlStruct {
-	Statement * hoist( Statement * originalStmt, std::list<Statement *> & init ) {
-		// If no hoisting is needed, skip:
-		if ( 0 == init.size() ) {
-			return originalStmt;
-		}
-
-		// Create compound statement, move initializers outside,
-		// the resut of the original stays as is.
-		CompoundStmt * block = new CompoundStmt();
-		std::list<Statement *> & stmts = block->get_kids();
-		stmts.splice( stmts.end(), init );
-
-		// Add for to the new block.
-		stmts.push_back( originalStmt );
-		return block;
-	}
-
-	Statement * ForExprMutator::postmutate( IfStmt * ifStmt ) {
-		return hoist( ifStmt, ifStmt->initialization );
-	}
-	Statement * ForExprMutator::postmutate( ForStmt * forStmt ) {
-		// hoist any initializer declarations to make them C89 (rather than C99)
-		return hoist( forStmt, forStmt->initialization );
-	}
-	Statement * ForExprMutator::postmutate( WhileDoStmt * whileDoStmt ) {
-		return hoist( whileDoStmt, whileDoStmt->initialization );
-	}
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ControlStruct/ForExprMutator.h
===================================================================
--- src/ControlStruct/ForExprMutator.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,36 +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.
-//
-// ForExprMutator.h --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Feb  1 09:18:50 2022
-// Update Count     : 7
-//
-
-#pragma once
-
-class IfStmt;
-class ForStmt;
-class WhileDoStmt;
-class Statement;
-
-namespace ControlStruct {
-	class ForExprMutator {
-	  public:
-		Statement * postmutate( IfStmt * );
-		Statement * postmutate( ForStmt * );
-		Statement * postmutate( WhileDoStmt * );
-	};
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ControlStruct/LabelFixer.cc
===================================================================
--- src/ControlStruct/LabelFixer.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,138 +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.
-//
-// LabelFixer.cc --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Feb  1 09:12:09 2022
-// Update Count     : 162
-//
-
-#include <cassert>                         // for assert
-#include <list>                            // for list, _List_iterator, list...
-#include <string>                          // for operator+, string, operator==
-#include <utility>                         // for pair
-
-#include "ControlStruct/LabelGenerator.h"  // for LabelGenerator
-#include "LabelFixer.h"
-#include "MLEMutator.h"                    // for MultiLevelExitMutator
-#include "SynTree/Declaration.h"           // for FunctionDecl
-#include "SynTree/Expression.h"            // for NameExpr, Expression, Unty...
-#include "SynTree/Statement.h"             // for Statement, BranchStmt, Com...
-
-namespace ControlStruct {
-bool LabelFixer::Entry::insideLoop() {
-	return ( dynamic_cast< ForStmt * > ( definition ) ||
-		dynamic_cast< WhileDoStmt * > ( definition )  );
-}
-
-LabelFixer::LabelFixer( LabelGenerator * gen ) : generator ( gen ) {
-	if ( generator == 0 )
-		generator = LabelGenerator::getGenerator();
-}
-
-void LabelFixer::previsit( FunctionDecl * ) {
-	// need to go into a nested function in a fresh state
-	GuardValue( labelTable );
-	labelTable.clear();
-}
-
-void LabelFixer::postvisit( FunctionDecl * functionDecl ) {
-	PassVisitor<MultiLevelExitMutator> mlem( resolveJumps(), generator );
-	// We start in the body so we can stop when we hit another FunctionDecl.
-	maybeMutate( functionDecl->statements, mlem );
-}
-
-// prune to at most one label definition for each statement
-void LabelFixer::previsit( Statement * stmt ) {
-	std::list< Label > &labels = stmt->get_labels();
-
-	if ( ! labels.empty() ) {
-		// only remember one label for each statement
-		Label current = setLabelsDef( labels, stmt );
-	} // if
-}
-
-void LabelFixer::previsit( BranchStmt * branchStmt ) {
-	previsit( ( Statement *)branchStmt );
-
-	// for labeled branches, add an entry to the label table
-	Label target = branchStmt->get_target();
-	if ( target != "" ) {
-		setLabelsUsg( target, branchStmt );
-	}
-}
-
-void LabelFixer::previsit( LabelAddressExpr * addrExpr ) {
-	Label & target = addrExpr->arg;
-	assert( target != "" );
-	setLabelsUsg( target, addrExpr );
-}
-
-
-// Sets the definition of the labelTable entry to be the provided statement for every label in
-// the list parameter. Happens for every kind of statement.
-Label LabelFixer::setLabelsDef( std::list< Label > & llabel, Statement * definition ) {
-	assert( definition != 0 );
-	assert( llabel.size() > 0 );
-
-	for ( std::list< Label >::iterator i = llabel.begin(); i != llabel.end(); i++ ) {
-		Label & l = *i;
-		l.set_statement( definition ); // attach statement to the label to be used later
-		if ( labelTable.find( l ) == labelTable.end() ) {
-			// All labels on this statement need to use the same entry,
-			// so this should only be created once.
-			// undefined and unused until now, add an entry
-			labelTable[ l ] = new Entry( definition );
-		} else if ( labelTable[ l ]->defined() ) {
-			// defined twice, error
-			SemanticError( l.get_statement()->location,
-				"Duplicate definition of label: " + l.get_name() );
-		} else {
-			// used previously, but undefined until now -> link with this entry
-			// Question: Is changing objects important?
-			delete labelTable[ l ];
-			labelTable[ l ] = new Entry( definition );
-		} // if
-	} // for
-
-	// Produce one of the labels attached to this statement to be temporarily used as the
-	// canonical label.
-	return labelTable[ llabel.front() ]->get_label();
-}
-
-// A label was used, add it to the table if it isn't already there
-template< typename UsageNode >
-void LabelFixer::setLabelsUsg( Label orgValue, UsageNode *use ) {
-	assert( use != 0 );
-
-	// add label with an unknown origin
-	if ( labelTable.find( orgValue ) == labelTable.end() ) {
-		labelTable[ orgValue ] = new Entry( 0 );
-	}
-}
-
-// Builds a table that maps a label to its defining statement.
-std::map<Label, Statement * > * LabelFixer::resolveJumps() {
-	std::map< Label, Statement * > *ret = new std::map< Label, Statement * >();
-	for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
-		if ( ! i->second->defined() ) {
-			SemanticError( i->first.get_statement()->location, "Use of undefined label: " + i->first.get_name() );
-		}
-		(*ret)[ i->first ] = i->second->get_definition();
-	}
-
-	return ret;
-}
-}  // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ControlStruct/LabelFixer.h
===================================================================
--- src/ControlStruct/LabelFixer.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,79 +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.
-//
-// LabelFixer.h --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jan 31 22:28:04 2022
-// Update Count     : 35
-//
-
-#pragma once
-
-#include <list>                    // for list
-#include <map>                     // for map
-
-#include "Common/PassVisitor.h"
-#include "Common/SemanticError.h"  // for SemanticError
-#include "SynTree/Label.h"         // for Label
-#include "SynTree/Visitor.h"       // for Visitor
-#include "SynTree/SynTree.h"       // for Visitor Nodes
-
-namespace ControlStruct {
-// normalizes label definitions and generates multi-level exit labels
-class LabelGenerator;
-
-class LabelFixer final : public WithGuards {
-  public:
-	LabelFixer( LabelGenerator *gen = 0 );
-
-	std::map < Label, Statement * > *resolveJumps();
-
-	// Declarations
-	void previsit( FunctionDecl *functionDecl );
-	void postvisit( FunctionDecl *functionDecl );
-
-	// Statements
-	void previsit( Statement *stmt );
-	void previsit( BranchStmt *branchStmt );
-
-	// Expressions
-	void previsit( LabelAddressExpr *addrExpr );
-
-	Label setLabelsDef( std::list< Label > &, Statement *definition );
-	template< typename UsageNode >
-	void setLabelsUsg( Label, UsageNode *usage = 0 );
-
-  private:
-	class Entry {
-		public:
-		Entry( Statement *to ) : definition( to ) {}
-		bool defined() { return ( definition != 0 ); }
-		bool insideLoop();
-
-		Label get_label() const { return label; }
-		void set_label( Label lab ) { label = lab; }
-
-		Statement *get_definition() const { return definition; }
-		void set_definition( Statement *def ) { definition = def; }
-
-	  private:
-		Label label;
-		Statement *definition;
-	};
-
-	std::map < Label, Entry *> labelTable;
-	LabelGenerator *generator;
-};
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ControlStruct/LabelGenerator.cc
===================================================================
--- src/ControlStruct/LabelGenerator.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,52 +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.
-//
-// LabelGenerator.cc --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jan 31 22:30:26 2022
-// Update Count     : 28
-//
-
-#include <iostream>             // for operator<<, basic_ostream
-#include <sstream>              // for ostringstream
-#include <list>                 // for list
-using namespace std;
-
-#include "LabelGenerator.h"
-
-#include "SynTree/Attribute.h"  // for Attribute
-#include "SynTree/Label.h"      // for Label, operator<<
-#include "SynTree/Statement.h"  // for Statement
-
-namespace ControlStruct {
-int LabelGenerator::current = 0;
-LabelGenerator * LabelGenerator::labelGenerator = nullptr;
-
-LabelGenerator * LabelGenerator::getGenerator() {
-	if ( LabelGenerator::labelGenerator == 0 )
-		LabelGenerator::labelGenerator = new LabelGenerator();
-	return labelGenerator;
-}
-
-Label LabelGenerator::newLabel( string suffix, Statement * stmt ) {
-	ostringstream os;
-	os << "__L_OLD" << current++ << "__" << suffix;
-	if ( stmt && ! stmt->get_labels().empty() ) {
-		os << "_" << stmt->get_labels().front() << "__";
-	} // if
-	string ret = os.str();
-	Label l( ret );
-	l.get_attributes().push_back( new Attribute( "unused" ) );
-	return l;
-}
-} // namespace ControlStruct
-
-// Local Variables: //
-// mode: c++ //
-// End: //
Index: c/ControlStruct/LabelGenerator.h
===================================================================
--- src/ControlStruct/LabelGenerator.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,45 +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.
-//
-// LabelGenerator.h --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jan 31 22:30:10 2022
-// Update Count     : 16
-//
-
-#pragma once
-
-#include <string>           // for string
-
-#include "SynTree/Label.h"  // for Label
-
-class Statement;
-
-namespace ast {
-class Stmt;
-class Label;
-}
-
-namespace ControlStruct {
-class LabelGenerator {
-	static int current;
-	static LabelGenerator *labelGenerator;
-  protected:
-	LabelGenerator() {}
-  public:
-	static LabelGenerator *getGenerator();
-	static Label newLabel(std::string suffix, Statement * stmt = nullptr);
-};
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ControlStruct/MLEMutator.cc
===================================================================
--- src/ControlStruct/MLEMutator.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,464 +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.
-//
-// MLEMutator.cc --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  2 20:18:57 2022
-// Update Count     : 227
-//
-
-// NOTE: There are two known subtle differences from the code that uC++ generates for the same input
-//   -CFA puts the break label inside at the end of a switch, uC++ puts it after
-//   -CFA puts the break label after a block, uC++ puts it inside at the end
-// It is unclear if these differences are important, but if they are, then the fix would go in this file, since this is
-// where these labels are generated.
-
-#include <ext/alloc_traits.h>              // for __alloc_traits<>::value_type
-#include <algorithm>                       // for find, find_if
-#include <cassert>                         // for assert, assertf
-#include <memory>                          // for allocator_traits<>::value_...
-
-#include "Common/ToString.hpp"             // for toString
-#include "ControlStruct/LabelGenerator.h"  // for LabelGenerator
-#include "MLEMutator.h"
-#include "SynTree/Attribute.h"             // for Attribute
-#include "SynTree/Expression.h"            // for Expression
-#include "SynTree/Statement.h"             // for BranchStmt, CompoundStmt
-
-namespace ControlStruct {
-	MultiLevelExitMutator::~MultiLevelExitMutator() {
-		delete targetTable;
-		targetTable = 0;
-	}
-	namespace {
-		bool isLoop( const MultiLevelExitMutator::Entry & e ) {
-			return dynamic_cast< WhileDoStmt * >( e.get_controlStructure() )
-				|| dynamic_cast< ForStmt * >( e.get_controlStructure() );
-		}
-		bool isSwitch( const MultiLevelExitMutator::Entry & e ) {
-			return dynamic_cast< SwitchStmt *>( e.get_controlStructure() );
-		}
-
-		bool isBreakTarget( const MultiLevelExitMutator::Entry & e ) {
-			return isLoop( e ) || isSwitch( e )
-				|| dynamic_cast< CompoundStmt *>( e.get_controlStructure() );
-		}
-		bool isContinueTarget( const MultiLevelExitMutator::Entry & e ) {
-			return isLoop( e );
-		}
-		bool isFallthroughTarget( const MultiLevelExitMutator::Entry & e ) {
-			return dynamic_cast< CaseStmt *>( e.get_controlStructure() );
-		}
-		bool isFallthroughDefaultTarget( const MultiLevelExitMutator::Entry & e ) {
-			return isSwitch( e );
-		}
-	} // namespace
-
-	void MultiLevelExitMutator::premutate( FunctionDecl * ) {
-		visit_children = false;
-	}
-
-	// break labels have to come after the statement they break out of, so mutate a statement, then if they inform us
-	// through the breakLabel field that they need a place to jump to on a break statement, add the break label to the
-	// body of statements
-	void MultiLevelExitMutator::fixBlock( std::list< Statement * > &kids, bool caseClause ) {
-		SemanticErrorException errors;
-
-		for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) {
-			if ( caseClause ) {
-				// once a label is seen, it's no longer a valid fallthrough target
-				for ( Label & l : (*k)->labels ) {
-					fallthroughLabels.erase( l );
-				}
-			}
-
-			// aggregate errors since the PassVisitor mutate loop was unrollled
-			try {
-				*k = (*k)->acceptMutator(*visitor);
-			} catch( SemanticErrorException &e ) {
-				errors.append( e );
-			}
-
-			if ( ! get_breakLabel().empty() ) {
-				std::list< Statement * >::iterator next = k+1;
-				std::list<Label> ls; ls.push_back( get_breakLabel() );
-				kids.insert( next, new NullStmt( ls ) );
-				set_breakLabel("");
-			} // if
-		} // for
-
-		if ( ! errors.isEmpty() ) {
-			throw errors;
-		}
-	}
-
-	void MultiLevelExitMutator::premutate( CompoundStmt *cmpndStmt ) {
-		visit_children = false;
-		bool labeledBlock = !(cmpndStmt->labels.empty());
-		if ( labeledBlock ) {
-			Label brkLabel = generator->newLabel("blockBreak", cmpndStmt);
-			enclosingControlStructures.push_back( Entry( cmpndStmt, brkLabel ) );
-			GuardAction( [this]() { enclosingControlStructures.pop_back(); } );
-		} // if
-
-		// a child statement may set the break label - if they do, attach it to the next statement
-		std::list< Statement * > &kids = cmpndStmt->kids;
-		fixBlock( kids );
-
-		if ( labeledBlock ) {
-			assert( ! enclosingControlStructures.empty() );
-			if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
-				set_breakLabel( enclosingControlStructures.back().useBreakExit() );
-			} // if
-		} // if
-	}
-
-
-	void addUnused( Statement * stmt, const Label & originalTarget ) {
-		// break/continue without a label doesn't need unused attribute
-		if ( originalTarget == "" ) return;
-		// add unused attribute to the originalTarget of a labelled break/continue
-		for ( Label & l : stmt->get_labels() ) {
-			// find the label to add unused attribute to
-			if ( l == originalTarget ) {
-				for ( Attribute * attr : l.get_attributes() ) {
-					// ensure attribute isn't added twice
-					if ( attr->get_name() == "unused" ) return;
-				}
-				l.get_attributes().push_back( new Attribute( "unused" ) );
-				return;
-			}
-		}
-		assertf( false, "CFA internal error: could not find label '%s' on statement %s",
-			originalTarget.get_name().c_str(), toString( stmt ).c_str() );
-	}
-
-
-	Statement *MultiLevelExitMutator::postmutate( BranchStmt *branchStmt ) {
-		std::string originalTarget = branchStmt->originalTarget;
-
-		std::list< Entry >::reverse_iterator targetEntry;
-		switch ( branchStmt->get_type() ) {
-			case BranchStmt::Goto:
-				return branchStmt;
-			case BranchStmt::Continue:
-			case BranchStmt::Break: {
-				bool isContinue = branchStmt->get_type() == BranchStmt::Continue;
-				// unlabeled break/continue
-				if ( branchStmt->get_target() == "" ) {
-					if ( isContinue ) {
-						// continue target is outermost loop
-						targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isContinueTarget );
-					} else {
-						// break target is outermost loop, switch, or block control structure
-						if ( enclosingControlStructures.empty() ) SemanticError( branchStmt->location, "'break' outside a loop, 'switch', or labelled block" );
-						targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isBreakTarget );
-					} // if
-				} else {
-					// labeled break/continue - lookup label in table to find attached control structure
-					targetEntry = std::find( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), (*targetTable)[branchStmt->get_target()] );
-				} // if
-				// ensure that selected target is valid
-				if ( targetEntry == enclosingControlStructures.rend() || (isContinue && ! isContinueTarget( *targetEntry ) ) ) {
-					SemanticError( branchStmt->location, toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
-				} // if
-				break;
-			}
-			case BranchStmt::FallThrough:
-				targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isFallthroughTarget );
-				// ensure that selected target is valid
-				if ( targetEntry == enclosingControlStructures.rend() ) {
-					SemanticError( branchStmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
-				} // if
-				if ( branchStmt->get_target() != "" ) {
-					// labelled fallthrough
-					// target must be in the set of valid fallthrough labels
-					if ( ! fallthroughLabels.count( branchStmt->get_target() ) ) {
-						SemanticError( branchStmt->location, toString( "'fallthrough' target must be a later case statement: ", originalTarget ) );
-					}
-					return new BranchStmt( originalTarget, BranchStmt::Goto );
-				}
-				break;
-			case BranchStmt::FallThroughDefault: {
-				// fallthrough default
-				targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isFallthroughDefaultTarget );
-
-				// ensure that fallthrough is within a switch or choose
-				if ( targetEntry == enclosingControlStructures.rend() ) {
-					SemanticError( branchStmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
-				} // if
-
-				// ensure that switch or choose has a default clause
-				SwitchStmt * switchStmt = strict_dynamic_cast< SwitchStmt * >( targetEntry->get_controlStructure() );
-				bool foundDefault = false;
-				for ( Statement * stmt : switchStmt->statements ) {
-					CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt );
-					if ( caseStmt->isDefault() ) {
-						foundDefault = true;
-					} // if
-				} // for
-				if ( ! foundDefault ) {
-					SemanticError( branchStmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose' control structure with a 'default' clause" );
-				}
-				break;
-			}
-
-			default:
-				assert( false );
-		} // switch
-
-		// branch error checks, get the appropriate label name and create a goto
-		Label exitLabel;
-		switch ( branchStmt->type ) {
-		  case BranchStmt::Break:
-				assert( targetEntry->useBreakExit() != "");
-				exitLabel = targetEntry->useBreakExit();
-				break;
-		  case BranchStmt::Continue:
-				assert( targetEntry->useContExit() != "");
-				exitLabel = targetEntry->useContExit();
-				break;
-		  case BranchStmt::FallThrough:
-				assert( targetEntry->useFallExit() != "");
-				exitLabel = targetEntry->useFallExit();
-				break;
-		  case BranchStmt::FallThroughDefault:
-				assert( targetEntry->useFallDefaultExit() != "");
-				exitLabel = targetEntry->useFallDefaultExit();
-				// check that fallthrough default comes before the default clause
-				if ( ! targetEntry->isFallDefaultValid() ) {
-					SemanticError( branchStmt->location, "'fallthrough default' must precede the 'default' clause" );
-				}
-				break;
-		  default:
-				assert(0);					// shouldn't be here
-		} // switch
-
-		// add unused attribute to label to silence warnings
-		addUnused( targetEntry->get_controlStructure(), branchStmt->originalTarget );
-
-		// transform break/continue statements into goto to simplify later handling of branches
-		delete branchStmt;
-		return new BranchStmt( exitLabel, BranchStmt::Goto );
-	}
-
-	Statement *MultiLevelExitMutator::mutateLoop( Statement *bodyLoop, Entry &e ) {
-		// only generate these when needed
-		if( !e.isContUsed() && !e.isBreakUsed() ) return bodyLoop;
-
-		// ensure loop body is a block
-		CompoundStmt * newBody = new CompoundStmt();
-		newBody->get_kids().push_back( bodyLoop );
-
-		if ( e.isContUsed() ) {
-			// continue label goes in the body as the last statement
-			std::list< Label > labels; labels.push_back( e.useContExit() );
-			newBody->get_kids().push_back( new NullStmt( labels ) );
-		} // if
-
-		if ( e.isBreakUsed() ) {
-			// break label goes after the loop -- it'll get set by the outer mutator if we do this
-			set_breakLabel( e.useBreakExit() );
-		} // if
-
-		return newBody;
-	}
-
-	template< typename LoopClass >
-	void MultiLevelExitMutator::prehandleLoopStmt( LoopClass * loopStmt ) {
-		// remember this as the most recent enclosing loop, then mutate the body of the loop -- this will determine
-		// whether brkLabel and contLabel are used with branch statements and will recursively do the same to nested
-		// loops
-		Label brkLabel = generator->newLabel("loopBreak", loopStmt);
-		Label contLabel = generator->newLabel("loopContinue", loopStmt);
-		enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) );
-		GuardAction( [this]() { enclosingControlStructures.pop_back(); } );
-	}
-
-	template< typename LoopClass >
-	Statement * MultiLevelExitMutator::posthandleLoopStmt( LoopClass * loopStmt ) {
-		assert( ! enclosingControlStructures.empty() );
-		Entry &e = enclosingControlStructures.back();
-		// sanity check that the enclosing loops have been popped correctly
-		assert ( e == loopStmt );
-
-		// this will take the necessary steps to add definitions of the previous two labels, if they are used.
-		loopStmt->body = mutateLoop( loopStmt->get_body(), e );
-		return loopStmt;
-	}
-
-	void MultiLevelExitMutator::premutate( WhileDoStmt * whileDoStmt ) {
-		return prehandleLoopStmt( whileDoStmt );
-	}
-
-	void MultiLevelExitMutator::premutate( ForStmt * forStmt ) {
-		return prehandleLoopStmt( forStmt );
-	}
-
-	Statement * MultiLevelExitMutator::postmutate( WhileDoStmt * whileDoStmt ) {
-		return posthandleLoopStmt( whileDoStmt );
-	}
-
-	Statement * MultiLevelExitMutator::postmutate( ForStmt * forStmt ) {
-		return posthandleLoopStmt( forStmt );
-	}
-
-	void MultiLevelExitMutator::premutate( IfStmt * ifStmt ) {
-		// generate a label for breaking out of a labeled if
-		bool labeledBlock = !(ifStmt->get_labels().empty());
-		if ( labeledBlock ) {
-			Label brkLabel = generator->newLabel("blockBreak", ifStmt);
-			enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) );
-			GuardAction( [this]() { enclosingControlStructures.pop_back(); } );
-		} // if
-	}
-
-	Statement * MultiLevelExitMutator::postmutate( IfStmt * ifStmt ) {
-		bool labeledBlock = !(ifStmt->get_labels().empty());
-		if ( labeledBlock ) {
-			if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
-				set_breakLabel( enclosingControlStructures.back().useBreakExit() );
-			} // if
-		} // if
-		return ifStmt;
-	}
-
-	void MultiLevelExitMutator::premutate( TryStmt * tryStmt ) {
-		// generate a label for breaking out of a labeled if
-		bool labeledBlock = !(tryStmt->get_labels().empty());
-		if ( labeledBlock ) {
-			Label brkLabel = generator->newLabel("blockBreak", tryStmt);
-			enclosingControlStructures.push_back( Entry( tryStmt, brkLabel ) );
-			GuardAction( [this]() { enclosingControlStructures.pop_back(); } );
-		} // if
-	}
-
-	Statement * MultiLevelExitMutator::postmutate( TryStmt * tryStmt ) {
-		bool labeledBlock = !(tryStmt->get_labels().empty());
-		if ( labeledBlock ) {
-			if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
-				set_breakLabel( enclosingControlStructures.back().useBreakExit() );
-			} // if
-		} // if
-		return tryStmt;
-	}
-
-	void MultiLevelExitMutator::premutate( FinallyStmt * ) {
-		GuardAction([this, old = std::move(enclosingControlStructures)]() {
-			enclosingControlStructures = std::move(old);
-		});
-		enclosingControlStructures = std::list<Entry>();
-		GuardValue( inFinally );
-		inFinally = true;
-	}
-
-	void MultiLevelExitMutator::premutate( ReturnStmt *returnStmt ) {
-		if ( inFinally ) {
-			SemanticError( returnStmt->location, "'return' may not appear in a finally clause" );
-		}
-	}
-
-	void MultiLevelExitMutator::premutate( CaseStmt *caseStmt ) {
-		visit_children = false;
-
-		// mark default as seen before visiting its statements to catch default loops
-		if ( caseStmt->isDefault() ) {
-			enclosingControlStructures.back().seenDefault();
-		} // if
-
-		caseStmt->condition = maybeMutate( caseStmt->condition, *visitor );
-		Label fallLabel = generator->newLabel( "fallThrough", caseStmt );
-		{
-			// ensure that stack isn't corrupted by exceptions in fixBlock
-			auto guard = makeFuncGuard( [&]() { enclosingControlStructures.push_back( Entry( caseStmt, fallLabel ) ); }, [this]() { enclosingControlStructures.pop_back(); } );
-
-			// empty case statement
-			if( ! caseStmt->stmts.empty() ) {
-				// the parser ensures that all statements in a case are grouped into a block
-				CompoundStmt * block = strict_dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() );
-				fixBlock( block->kids, true );
-
-				// add fallthrough label if necessary
-				assert( ! enclosingControlStructures.empty() );
-				if ( enclosingControlStructures.back().isFallUsed() ) {
-					std::list<Label> ls{ enclosingControlStructures.back().useFallExit() };
-					caseStmt->stmts.push_back( new NullStmt( ls ) );
-				} // if
-			} // if
-		}
-		assert( ! enclosingControlStructures.empty() );
-		assertf( dynamic_cast<SwitchStmt *>( enclosingControlStructures.back().get_controlStructure() ),
-				 "CFA internal error: control structure enclosing a case clause must be a switch, but is: %s",
-				 toCString( enclosingControlStructures.back().get_controlStructure() ) );
-		if ( caseStmt->isDefault() ) {
-			if ( enclosingControlStructures.back().isFallDefaultUsed() ) {
-				// add fallthrough default label if necessary
-				std::list<Label> ls{ enclosingControlStructures.back().useFallDefaultExit() };
-				caseStmt->stmts.push_front( new NullStmt( ls ) );
-			} // if
-		} // if
-	}
-
-	void MultiLevelExitMutator::premutate( SwitchStmt *switchStmt ) {
-		// generate a label for breaking out of a labeled switch
-		Label brkLabel = generator->newLabel("switchBreak", switchStmt);
-		auto it = std::find_if( switchStmt->statements.rbegin(), switchStmt->statements.rend(), [](Statement * stmt) {
-			CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt );
-			return caseStmt->isDefault();
-		});
-		CaseStmt * defaultCase = it != switchStmt->statements.rend() ? strict_dynamic_cast<CaseStmt *>( *it ) : nullptr;
-		Label fallDefaultLabel = defaultCase ? generator->newLabel( "fallThroughDefault", defaultCase ) : "";
-		enclosingControlStructures.push_back( Entry(switchStmt, brkLabel, fallDefaultLabel) );
-		GuardAction( [this]() { enclosingControlStructures.pop_back(); } );
-
-		// Collect valid labels for fallthrough. This is initially all labels at the same level as a case statement.
-		// As labels are seen during traversal, they are removed, since fallthrough is not allowed to jump backwards.
-		for ( Statement * stmt : switchStmt->statements ) {
-			CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt );
-			if ( caseStmt->stmts.empty() ) continue;
-			CompoundStmt * block = dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() );
-			for ( Statement * stmt : block->kids ) {
-				for ( Label & l : stmt->labels ) {
-					fallthroughLabels.insert( l );
-				}
-			}
-		}
-	}
-
-	Statement * MultiLevelExitMutator::postmutate( SwitchStmt * switchStmt ) {
-		Entry &e = enclosingControlStructures.back();
-		assert ( e == switchStmt );
-
-		// only generate break label if labeled break is used
-		if ( e.isBreakUsed() ) {
-			// for the purposes of keeping switch statements uniform (i.e. all statements that are direct children of a
-			// switch should be CastStmts), append the exit label + break to the last case statement; create a default
-			// case if there are no cases
-			std::list< Statement * > &statements = switchStmt->statements;
-			if ( statements.empty() ) {
-				statements.push_back( CaseStmt::makeDefault() );
-			} // if
-
-			if ( CaseStmt * c = dynamic_cast< CaseStmt * >( statements.back() ) ) {
-				Statement * stmt = new BranchStmt( Label("brkLabel"), BranchStmt::Break );
-				stmt->labels.push_back( e.useBreakExit() );
-				c->stmts.push_back( stmt );
-			} else assert(0); // as of this point, all statements of a switch are still CaseStmts
-		} // if
-
-		assert ( enclosingControlStructures.back() == switchStmt );
-		return switchStmt;
-	}
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ControlStruct/MLEMutator.h
===================================================================
--- src/ControlStruct/MLEMutator.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,134 +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.
-//
-// MLEMutator.h --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Feb  1 09:27:24 2022
-// Update Count     : 50
-//
-
-#pragma once
-
-#include <list>                    // for list
-#include <map>                     // for map
-#include <string>                  // for string
-#include <set>                     // for unordered_set
-
-#include "Common/PassVisitor.h"
-#include "Common/SemanticError.h"  // for SemanticError
-#include "SynTree/Label.h"         // for Label
-#include "SynTree/Mutator.h"       // for Mutator
-#include "SynTree/SynTree.h"       // for Visitor Nodes
-
-namespace ControlStruct {
-	class LabelGenerator;
-
-	class MultiLevelExitMutator : public WithVisitorRef<MultiLevelExitMutator>,
-			public WithShortCircuiting, public WithGuards {
-	  public:
-		class Entry;
-		MultiLevelExitMutator( std::map<Label, Statement *> *t, LabelGenerator *gen = 0 ) :
-			targetTable( t ), breakLabel(std::string("")), generator( gen ) {}
-		~MultiLevelExitMutator();
-
-		void premutate( FunctionDecl * );
-
-		void premutate( CompoundStmt *cmpndStmt );
-		Statement * postmutate( BranchStmt *branchStmt );
-		void premutate( WhileDoStmt *whileDoStmt );
-		Statement * postmutate( WhileDoStmt *whileDoStmt );
-		void premutate( ForStmt *forStmt );
-		Statement * postmutate( ForStmt *forStmt );
-		void premutate( CaseStmt *caseStmt );
-		void premutate( IfStmt *ifStmt );
-		Statement * postmutate( IfStmt *ifStmt );
-		void premutate( SwitchStmt *switchStmt );
-		Statement * postmutate( SwitchStmt *switchStmt );
-		void premutate( ReturnStmt *returnStmt );
-		void premutate( TryStmt *tryStmt );
-		Statement * postmutate( TryStmt *tryStmt );
-		void premutate( FinallyStmt *finallyStmt );
-
-		Statement *mutateLoop( Statement *bodyLoop, Entry &e );
-
-		Label &get_breakLabel() { return breakLabel; }
-		void set_breakLabel( Label newValue ) { breakLabel = newValue; }
-
-		class Entry {
-		  public:
-			// specialized constructors for each combination of statement with labelled break/continue/fallthrough that is valid to cleanup the use cases
-			explicit Entry( ForStmt *stmt, Label breakExit, Label contExit ) :
-				stmt( stmt ), breakExit( breakExit ), contExit( contExit ) {}
-
-			explicit Entry( WhileDoStmt *stmt, Label breakExit, Label contExit ) :
-				stmt( stmt ), breakExit( breakExit ), contExit( contExit ) {}
-
-			explicit Entry( CompoundStmt *stmt, Label breakExit ) :
-				stmt( stmt ), breakExit( breakExit ) {}
-
-			explicit Entry( IfStmt *stmt, Label breakExit ) :
-				stmt( stmt ), breakExit( breakExit ) {}
-
-			explicit Entry( CaseStmt *stmt, Label fallExit ) :
-				stmt( stmt ), fallExit( fallExit ) {}
-
-			explicit Entry( SwitchStmt *stmt, Label breakExit, Label fallDefaultExit ) :
-				stmt( stmt ), breakExit( breakExit ), fallDefaultExit( fallDefaultExit ) {}
-
-			explicit Entry( TryStmt *stmt, Label breakExit ) :
-				stmt( stmt ), breakExit( breakExit ) {}
-
-			bool operator==( const Statement *other ) { return stmt == other; }
-			bool operator!=( const Statement *other ) { return stmt != other; }
-
-			bool operator==( const Entry &other ) { return stmt == other.get_controlStructure(); }
-
-			Statement *get_controlStructure() const { return stmt; }
-
-			Label useContExit() { contUsed = true; return contExit; }
-			Label useBreakExit() { breakUsed = true; return breakExit; }
-			Label useFallExit() { fallUsed = true; return fallExit; }
-			Label useFallDefaultExit() { fallDefaultUsed = true; return fallDefaultExit; }
-
-			bool isContUsed() const { return contUsed; }
-			bool isBreakUsed() const { return breakUsed; }
-			bool isFallUsed() const { return fallUsed; }
-			bool isFallDefaultUsed() const { return fallDefaultUsed; }
-			void seenDefault() { fallDefaultValid = false; }
-			bool isFallDefaultValid() const { return fallDefaultValid; }
-		  private:
-			Statement *stmt;
-			Label breakExit, contExit, fallExit, fallDefaultExit;
-			bool breakUsed = false, contUsed = false, fallUsed = false, fallDefaultUsed = false;
-			bool fallDefaultValid = true;
-		};
-
-	  private:
-		std::map< Label, Statement * > *targetTable;
-		std::set< Label > fallthroughLabels;
-		std::list< Entry > enclosingControlStructures;
-		Label breakLabel;
-		LabelGenerator *generator;
-		bool inFinally = false;
-
-		template< typename LoopClass >
-		void prehandleLoopStmt( LoopClass * loopStmt );
-
-		template< typename LoopClass >
-		Statement * posthandleLoopStmt( LoopClass * loopStmt );
-
-		void fixBlock( std::list< Statement * > &kids, bool caseClause = false );
-	};
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ControlStruct/Mutate.cc
===================================================================
--- src/ControlStruct/Mutate.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,45 +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.
-//
-// Mutate.cc --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Feb 16 03:22:07 2020
-// Update Count     : 10
-//
-
-#include <iterator>                // for back_inserter, inserter
-#include <list>                    // for list
-
-#include "Common/PassVisitor.h"    // for mutateAll
-#include "ForExprMutator.h"        // for ForExprMutator
-#include "LabelFixer.h"            // for LabelFixer
-#include "Mutate.h"
-#include "SynTree/Declaration.h"   // for Declaration
-#include "SynTree/Mutator.h"       // for mutateAll
-
-#include "Common/PassVisitor.h"    // for PassVisitor
-#include "SynTree/Visitor.h"       // for acceptAll
-
-namespace ControlStruct {
-	void fixLabels( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<LabelFixer> lfix;
-		acceptAll( translationUnit, lfix );
-	}
-
-	void hoistControlDecls( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<ForExprMutator> formut;
-		mutateAll( translationUnit, formut );
-	}
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ControlStruct/Mutate.h
===================================================================
--- src/ControlStruct/Mutate.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,35 +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.
-//
-// Mutate.h --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:17:59 2017
-// Update Count     : 3
-//
-
-#pragma once
-
-#include <list>  // for list
-
-class Declaration;
-
-/// Desugars Cforall control structures
-namespace ControlStruct {
-	/// normalizes label definitions and generates multi-level exit labels
-	void fixLabels( std::list< Declaration * > & translationUnit );
-
-	/// hoist initialization out of for statements
-	void hoistControlDecls( std::list< Declaration * > & translationUnit );
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/ControlStruct/module.mk
===================================================================
--- src/ControlStruct/module.mk	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ControlStruct/module.mk	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,27 +16,15 @@
 
 SRC += \
-	ControlStruct/ExceptDecl.cc \
 	ControlStruct/ExceptDeclNew.cpp \
 	ControlStruct/ExceptDecl.h \
 	ControlStruct/ExceptTranslateNew.cpp \
-	ControlStruct/ExceptTranslate.cc \
 	ControlStruct/ExceptTranslate.h \
 	ControlStruct/FixLabels.cpp \
 	ControlStruct/FixLabels.hpp \
-	ControlStruct/ForExprMutator.cc \
-	ControlStruct/ForExprMutator.h \
 	ControlStruct/HoistControlDecls.cpp \
 	ControlStruct/HoistControlDecls.hpp \
-	ControlStruct/LabelFixer.cc \
-	ControlStruct/LabelFixer.h \
-	ControlStruct/LabelGenerator.cc \
-	ControlStruct/LabelGenerator.h \
 	ControlStruct/LabelGeneratorNew.cpp \
 	ControlStruct/LabelGeneratorNew.hpp \
-	ControlStruct/MLEMutator.cc \
-	ControlStruct/MLEMutator.h \
 	ControlStruct/MultiLevelExit.cpp \
-	ControlStruct/MultiLevelExit.hpp \
-	ControlStruct/Mutate.cc \
-	ControlStruct/Mutate.h
+	ControlStruct/MultiLevelExit.hpp
 
Index: c/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,1910 +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.
-//
-// Box.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Dec 19 16:36:00 2022
-// Update Count     : 348
-//
-
-#include "Box.h"
-
-#include <algorithm>                     // for mismatch
-#include <cassert>                       // for assert, strict_dynamic_cast
-#include <iostream>                      // for operator<<, stringstream
-#include <list>                          // for list, list<>::iterator, _Lis...
-#include <map>                           // for _Rb_tree_const_iterator, map
-#include <memory>                        // for auto_ptr
-#include <set>                           // for set
-#include <string>                        // for string, allocator, basic_string
-#include <utility>                       // for pair
-
-#include "CodeGen/OperatorTable.h"
-#include "Common/PassVisitor.h"          // for PassVisitor
-#include "Common/ScopedMap.h"            // for ScopedMap, ScopedMap<>::iter...
-#include "Common/SemanticError.h"        // for SemanticError
-#include "Common/UniqueName.h"           // for UniqueName
-#include "Common/ToString.hpp"           // for toCString
-#include "FindFunction.h"                // for findFunction, findAndReplace...
-#include "GenPoly/ErasableScopedMap.h"   // for ErasableScopedMap<>::const_i...
-#include "GenPoly/GenPoly.h"             // for TyVarMap, isPolyType, mangle...
-#include "InitTweak/InitTweak.h"         // for getFunctionName, isAssignment
-#include "Lvalue.h"                      // for generalizedLvalue
-#include "ResolvExpr/Unify.h"            // for typesCompatible
-#include "ScopedSet.h"                   // for ScopedSet, ScopedSet<>::iter...
-#include "ScrubTyVars.h"                 // for ScrubTyVars
-#include "SymTab/Indexer.h"              // for Indexer
-#include "SymTab/Mangler.h"              // for Mangler
-#include "SynTree/LinkageSpec.h"         // for C, Spec, Cforall, Intrinsic
-#include "SynTree/Attribute.h"           // for Attribute
-#include "SynTree/Constant.h"            // for Constant
-#include "SynTree/Declaration.h"         // for DeclarationWithType, ObjectDecl
-#include "SynTree/Expression.h"          // for ApplicationExpr, UntypedExpr
-#include "SynTree/Initializer.h"         // for SingleInit, Initializer, Lis...
-#include "SynTree/Label.h"               // for Label
-#include "SynTree/Mutator.h"             // for maybeMutate, Mutator, mutateAll
-#include "SynTree/Statement.h"           // for ExprStmt, DeclStmt, ReturnStmt
-#include "SynTree/SynTree.h"             // for UniqueId
-#include "SynTree/Type.h"                // for Type, FunctionType, PointerType
-#include "SynTree/TypeSubstitution.h"    // for TypeSubstitution, operator<<
-
-namespace GenPoly {
-	namespace {
-		FunctionType *makeAdapterType( FunctionType const *adaptee, const TyVarMap &tyVars );
-
-		class BoxPass {
-		protected:
-			BoxPass() : scopeTyVars( TypeDecl::Data{} ) {}
-			TyVarMap scopeTyVars;
-		};
-
-		/// Adds layout-generation functions to polymorphic types.
-		class LayoutFunctionBuilder final : public WithDeclsToAdd, public WithVisitorRef<LayoutFunctionBuilder>, public WithShortCircuiting {
-		public:
-			void previsit( StructDecl *structDecl );
-			void previsit( UnionDecl *unionDecl );
-		};
-
-		/// Updates the call sites of polymorphic functions.
-		/// Replaces polymorphic return types with out-parameters,
-		/// replaces calls to polymorphic functions with adapter calls,
-		/// and adds appropriate type variables to the function call.
-		class CallAdapter final : public BoxPass, public WithConstTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<CallAdapter>, public WithShortCircuiting {
-		  public:
-			CallAdapter();
-
-			void premutate( Declaration * declaration );
-			void premutate( FunctionDecl * functionDecl );
-			void premutate( TypeDecl * typeDecl );
-			void premutate( CommaExpr * commaExpr );
-			Expression * postmutate( ApplicationExpr * appExpr );
-			Expression * postmutate( UntypedExpr *expr );
-			void premutate( AddressExpr * addrExpr );
-			Expression * postmutate( AddressExpr * addrExpr );
-			void premutate( ReturnStmt * returnStmt );
-			void premutate( PointerType * pointerType );
-			void premutate( FunctionType * functionType );
-
-			void beginScope();
-			void endScope();
-		  private:
-			/// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
-			/// Will insert 0, 2 or 3 more arguments.
-			std::list< Expression *>::iterator passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
-			/// passes extra type parameters into a polymorphic function application
-			/// Returns an iterator to the first argument after the added
-			/// arguments, which are added at the beginning.
-			std::list< Expression *>::iterator passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars );
-			/// wraps a function application with a new temporary for the out-parameter return value
-			/// The new out-parameter is the new first parameter.
-			Expression *addRetParam( ApplicationExpr *appExpr, Type *retType );
-			/// wraps a function application returning a polymorphic type with a new temporary for the out-parameter return value
-			Expression *addDynRetParam( ApplicationExpr *appExpr, Type *polyType );
-			/// Converts a function call into a call of the adapter with the
-			/// original function as the first argument (all other arguments
-			/// are pushed back). May adjust return value.
-			Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function );
-			/// Modifies the `arg`, replacing it with a boxed expression
-			/// that matches `formal` under the current TyVarMap.
-			void boxParam( Expression *&arg, Type *formal, const TyVarMap &exprTyVars );
-			/// Box an argument of `appExpr` for each parameter in `function`
-			/// starting at `arg`.
-			/// `exprTyVars` is the function's type variables.
-			void boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars );
-			/// Boxes each assertion and inserts them into `appExpr` at
-			/// `arg`. `exprTyVars` is the function's type variables.
-			void addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars );
-			/// Stores assignment operators from assertion list in local map of assignment operations
-			void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
-			/// Creates an adapter definition from `adaptee` to `realType`, using
-			/// `mangleName` as the base name for the adapter. `tyVars` is the map of
-			/// type variables for the function type of the adapted expression.
-			FunctionDecl *makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
-			/// Replaces intrinsic operator functions with their arithmetic desugaring
-			Expression *handleIntrinsics( ApplicationExpr *appExpr );
-			/// Inserts a new temporary variable into the current scope with an auto-generated name
-			ObjectDecl *makeTemporary( Type *type );
-
-			ScopedMap< std::string, DeclarationWithType* > adapters;     ///< Set of adapter functions in the current scope
-
-			std::map< ApplicationExpr *, Expression * > retVals;
-
-			DeclarationWithType *retval;
-			UniqueName tempNamer;
-		};
-
-		/// Updates declarations (and types) that require adapters.
-		/// * Moves polymorphic returns in function types to pointer-type parameters
-		/// * adds type size and assertion parameters to parameter lists
-		struct DeclAdapter final : public BoxPass, public WithGuards {
-			void handleAggDecl();
-
-			DeclarationWithType * postmutate( FunctionDecl *functionDecl );
-			void premutate( StructDecl *structDecl );
-			void premutate( UnionDecl *unionDecl );
-			void premutate( TraitDecl *unionDecl );
-			void premutate( TypeDecl *typeDecl );
-			void premutate( PointerType *pointerType );
-			void premutate( FunctionType *funcType );
-
-		  private:
-			void addAdapters( FunctionType *functionType );
-
-			std::map< UniqueId, std::string > adapterName;
-		};
-
-		/// * Replaces member and size/align/offsetof expressions on polymorphic generic types with calculated expressions.
-		/// * Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference
-		/// * Calculates polymorphic offsetof expressions from offset array
-		/// * Inserts dynamic calculation of polymorphic type layouts where needed
-		class PolyGenericCalculator final : public BoxPass, public WithGuards, public WithVisitorRef<PolyGenericCalculator>, public WithStmtsToAdd, public WithDeclsToAdd, public WithConstTypeSubstitution {
-		public:
-			PolyGenericCalculator();
-
-			void premutate( ObjectDecl *objectDecl );
-			void premutate( FunctionDecl *functionDecl );
-			void premutate( TypedefDecl *objectDecl );
-			void premutate( TypeDecl *objectDecl );
-			Declaration * postmutate( TypeDecl *TraitDecl );
-			void premutate( PointerType *pointerType );
-			void premutate( FunctionType *funcType );
-			void premutate( DeclStmt *declStmt );
-			Expression *postmutate( MemberExpr *memberExpr );
-			void premutate( AddressExpr *addrExpr );
-			Expression *postmutate( AddressExpr *addrExpr );
-			Expression *postmutate( SizeofExpr *sizeofExpr );
-			Expression *postmutate( AlignofExpr *alignofExpr );
-			Expression *postmutate( OffsetofExpr *offsetofExpr );
-			Expression *postmutate( OffsetPackExpr *offsetPackExpr );
-			void premutate( StructDecl * );
-			void premutate( UnionDecl * );
-
-			void beginScope();
-			void endScope();
-
-		private:
-			/// Makes a new variable in the current scope with the given name, type & optional initializer
-			ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 );
-			/// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns
-			bool findGeneric( Type const *ty );
-			/// adds type parameters to the layout call; will generate the appropriate parameters if needed
-			void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );
-			/// change the type of generic aggregate members to char[]
-			void mutateMembers( AggregateDecl * aggrDecl );
-			/// returns the calculated sizeof expression for ty, or nullptr for use C sizeof()
-			Expression* genSizeof( Type* ty );
-
-			/// Enters a new scope for type-variables, adding the type variables from ty
-			void beginTypeScope( Type *ty );
-			/// Enters a new scope for knowLayouts and knownOffsets and queues exit calls
-			void beginGenericScope();
-
-			ScopedSet< std::string > knownLayouts;          ///< Set of generic type layouts known in the current scope, indexed by sizeofName
-			ScopedSet< std::string > knownOffsets;          ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
-			UniqueName bufNamer;                           ///< Namer for VLA buffers
-			Expression * addrMember = nullptr;             ///< AddressExpr argument is MemberExpr?
-			bool expect_func_type = false;                 ///< used to avoid recursing too deep in type decls
-		};
-
-		/// Erases unneeded/unwanted polymorphic information.
-		/// Replaces initialization of polymorphic values with alloca,
-		/// declaration of dtype/ftype with appropriate void expression,
-		/// sizeof expressions of polymorphic types with the proper variable,
-		/// and strips fields from generic struct declarations.
-		struct Eraser final {
-			void premutate( ObjectDecl * objectDecl );
-			void premutate( FunctionDecl * functionDecl );
-			void premutate( TypedefDecl * typedefDecl );
-			void premutate( StructDecl * structDecl );
-			void premutate( UnionDecl * unionDecl );
-		};
-	} // anonymous namespace
-
-	void box( std::list< Declaration *>& translationUnit ) {
-		PassVisitor<LayoutFunctionBuilder> layoutBuilder;
-		PassVisitor<CallAdapter> callAdapter;
-		PassVisitor<DeclAdapter> declAdapter;
-		PassVisitor<PolyGenericCalculator> polyCalculator;
-		PassVisitor<Eraser> eraser;
-
-		acceptAll( translationUnit, layoutBuilder );
-		mutateAll( translationUnit, callAdapter );
-		mutateAll( translationUnit, declAdapter );
-		mutateAll( translationUnit, polyCalculator );
-		mutateAll( translationUnit, eraser );
-	}
-
-////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////
-
-	/// Get a list of type declarations that will affect a layout function
-	std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {
-		std::list< TypeDecl * > otypeDecls;
-
-		for ( TypeDecl * const decl : decls ) {
-			if ( decl->isComplete() ) {
-				otypeDecls.push_back( decl );
-			}
-		}
-
-		return otypeDecls;
-	}
-
-	/// Adds parameters for otype layout to a function type
-	void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {
-		BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-
-		for ( TypeDecl * const param : otypeParams ) {
-			TypeInstType paramType( Type::Qualifiers(), param->get_name(), param );
-			std::string paramName = mangleType( &paramType );
-			layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( paramName ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
-			layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( paramName ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
-		}
-	}
-
-	/// Builds a layout function declaration
-	FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, bool isInFunction, FunctionType *layoutFnType ) {
-		// Routines at global scope marked "static" to prevent multiple definitions is separate translation units
-		// because each unit generates copies of the default routines for each aggregate.
-		FunctionDecl *layoutDecl = new FunctionDecl( layoutofName( typeDecl ),
-													 isInFunction ? Type::StorageClasses() : Type::StorageClasses( Type::Static ),
-													 LinkageSpec::AutoGen, layoutFnType, new CompoundStmt(),
-													 std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) );
-		layoutDecl->fixUniqueId();
-		return layoutDecl;
-	}
-
-	/// Makes a binary operation
-	Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) {
-		UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
-		expr->args.push_back( lhs );
-		expr->args.push_back( rhs );
-		return expr;
-	}
-
-	/// Returns the dereference of a local pointer variable
-	Expression *derefVar( ObjectDecl *var ) {
-		return UntypedExpr::createDeref( new VariableExpr( var ) );
-	}
-
-	/// makes an if-statement with a single-expression if-block and no then block
-	Statement *makeCond( Expression *cond, Expression *ifPart ) {
-		return new IfStmt( cond, new ExprStmt( ifPart ), 0 );
-	}
-
-	/// makes a statement that assigns rhs to lhs if lhs < rhs
-	Statement *makeAssignMax( Expression *lhs, Expression *rhs ) {
-		return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) );
-	}
-
-	/// makes a statement that aligns lhs to rhs (rhs should be an integer power of two)
-	Statement *makeAlignTo( Expression *lhs, Expression *rhs ) {
-		// check that the lhs is zeroed out to the level of rhs
-		Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant::from_ulong( 1 ) ) ) );
-		// if not aligned, increment to alignment
-		Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) );
-		return makeCond( ifCond, ifExpr );
-	}
-
-	/// adds an expression to a compound statement
-	void addExpr( CompoundStmt *stmts, Expression *expr ) {
-		stmts->get_kids().push_back( new ExprStmt( expr ) );
-	}
-
-	/// adds a statement to a compound statement
-	void addStmt( CompoundStmt *stmts, Statement *stmt ) {
-		stmts->get_kids().push_back( stmt );
-	}
-
-	void LayoutFunctionBuilder::previsit( StructDecl *structDecl ) {
-		// do not generate layout function for "empty" tag structs
-		visit_children = false;
-		if ( structDecl->get_members().empty() ) return;
-
-		// get parameters that can change layout, exiting early if none
-		std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );
-		if ( otypeParams.empty() ) return;
-
-		// build layout function signature
-		FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
-		BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-		PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
-
-		ObjectDecl *sizeParam = new ObjectDecl( sizeofName( structDecl->get_name() ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
-		layoutFnType->get_parameters().push_back( sizeParam );
-		ObjectDecl *alignParam = new ObjectDecl( alignofName( structDecl->get_name() ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
-		layoutFnType->get_parameters().push_back( alignParam );
-		ObjectDecl *offsetParam = new ObjectDecl( offsetofName( structDecl->get_name() ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
-		layoutFnType->get_parameters().push_back( offsetParam );
-		addOtypeParams( layoutFnType, otypeParams );
-
-		// build function decl
-		FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, isInFunction(), layoutFnType );
-
-		// calculate struct layout in function body
-
-		// initialize size and alignment to 0 and 1 (will have at least one member to re-edit size)
-		addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant::from_ulong( 0 ) ) ) );
-		addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant::from_ulong( 1 ) ) ) );
-		for ( auto index_member : enumerate( structDecl->members ) ) {
-			DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( index_member.val );
-			assert( dwt );
-			Type *memberType = dwt->get_type();
-
-			if ( 0 < index_member.idx ) {
-				// make sure all members after the first (automatically aligned at 0) are properly padded for alignment
-				addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );
-			}
-
-			// place current size in the current offset index
-			addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from_ulong( index_member.idx ) ) ),
-			                                                      derefVar( sizeParam ) ) );
-
-			// add member size to current size
-			addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
-
-			// take max of member alignment and global alignment
-			addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
-		}
-		// make sure the type is end-padded to a multiple of its alignment
-		addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
-
-		declsToAddAfter.push_back( layoutDecl );
-	}
-
-	void LayoutFunctionBuilder::previsit( UnionDecl *unionDecl ) {
-		// do not generate layout function for "empty" tag unions
-		visit_children = false;
-		if ( unionDecl->get_members().empty() ) return;
-
-		// get parameters that can change layout, exiting early if none
-		std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
-		if ( otypeParams.empty() ) return;
-
-		// build layout function signature
-		FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
-		BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-		PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
-
-		ObjectDecl *sizeParam = new ObjectDecl( sizeofName( unionDecl->get_name() ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
-		layoutFnType->get_parameters().push_back( sizeParam );
-		ObjectDecl *alignParam = new ObjectDecl( alignofName( unionDecl->get_name() ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
-		layoutFnType->get_parameters().push_back( alignParam );
-		addOtypeParams( layoutFnType, otypeParams );
-
-		// build function decl
-		FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, isInFunction(), layoutFnType );
-
-		// calculate union layout in function body
-		addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant::from_ulong( 1 ) ) ) );
-		addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant::from_ulong( 1 ) ) ) );
-		for ( Declaration * const member : unionDecl->members ) {
-			DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( member );
-			assert( dwt );
-			Type *memberType = dwt->get_type();
-
-			// take max member size and global size
-			addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
-
-			// take max of member alignment and global alignment
-			addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
-		}
-		// make sure the type is end-padded to a multiple of its alignment
-		addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
-
-		declsToAddAfter.push_back( layoutDecl );
-	}
-
-////////////////////////////////////////////// CallAdapter //////////////////////////////////////
-
-	namespace {
-		std::string makePolyMonoSuffix( FunctionType const * function, const TyVarMap &tyVars ) {
-			// NOTE: this function previously used isPolyObj, which failed to produce
-			// the correct thing in some situations. It's not clear to me why this wasn't working.
-
-			// if the return type or a parameter type involved polymorphic types, then the adapter will need
-			// to take those polymorphic types as pointers. Therefore, there can be two different functions
-			// with the same mangled name, so we need to further mangle the names.
-			std::stringstream name;
-			for ( DeclarationWithType const * const ret : function->returnVals ) {
-				name << ( isPolyType( ret->get_type(), tyVars ) ? 'P' : 'M' );
-			}
-			name << '_';
-			for ( DeclarationWithType const * const arg : function->parameters ) {
-				name << ( isPolyType( arg->get_type(), tyVars ) ? 'P' : 'M' );
-			}
-			return name.str();
-		}
-
-		std::string mangleAdapterName( FunctionType const * function, const TyVarMap &tyVars ) {
-			return SymTab::Mangler::mangle( function ) + makePolyMonoSuffix( function, tyVars );
-		}
-
-		std::string makeAdapterName( const std::string &mangleName ) {
-			return "_adapter" + mangleName;
-		}
-
-		/// Replaces a polymorphic type with its concrete equivalant under the current environment (returns itself if concrete).
-		/// If `doClone` is set to false, will not clone interior types
-		Type *replaceWithConcrete( Type *type, TypeSubstitution const * env, bool doClone = true );
-
-		CallAdapter::CallAdapter() : tempNamer( "_temp" ) {}
-
-		void CallAdapter::premutate( Declaration * ) {
-			// Prevent type declaration information from leaking out.
-			GuardScope( scopeTyVars );
-		}
-
-		void CallAdapter::premutate( FunctionDecl *functionDecl ) {
-			if ( functionDecl->get_statements() ) {		// empty routine body ?
-				// std::cerr << "mutating function: " << functionDecl->get_mangleName() << std::endl;
-				GuardScope( scopeTyVars );
-				GuardValue( retval );
-
-				// process polymorphic return value
-				retval = nullptr;
-				FunctionType *functionType = functionDecl->type;
-				if ( isDynRet( functionType ) && functionDecl->linkage != LinkageSpec::C ) {
-					retval = functionType->returnVals.front();
-
-					// give names to unnamed return values
-					if ( retval->name == "" ) {
-						retval->name = "_retparm";
-						retval->linkage = LinkageSpec::C;
-					} // if
-				} // if
-
-				makeTyVarMap( functionType, scopeTyVars );
-
-				std::list< FunctionType const *> functions;
-				for ( TypeDecl * const tyVar : functionType->forall ) {
-					for ( DeclarationWithType * const assert : tyVar->assertions ) {
-						findFunction( assert->get_type(), functions, scopeTyVars, needsAdapter );
-					} // for
-				} // for
-				for ( DeclarationWithType * const arg : functionType->parameters ) {
-					findFunction( arg->get_type(), functions, scopeTyVars, needsAdapter );
-				} // for
-
-				for ( FunctionType const * const funType : functions ) {
-					std::string mangleName = mangleAdapterName( funType, scopeTyVars );
-					if ( !adapters.contains( mangleName ) ) {
-						std::string adapterName = makeAdapterName( mangleName );
-						adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( funType, scopeTyVars ) ), nullptr ) ) );
-					} // if
-				} // for
-				// std::cerr << "end function: " << functionDecl->get_mangleName() << std::endl;
-			} // if
-		}
-
-		void CallAdapter::premutate( TypeDecl *typeDecl ) {
-			addToTyVarMap( typeDecl, scopeTyVars );
-		}
-
-		void CallAdapter::premutate( CommaExpr *commaExpr ) {
-			// Attempting to find application expressions that were mutated by the copy constructor passes
-			// to use an explicit return variable, so that the variable can be reused as a parameter to the
-			// call rather than creating a new temp variable. Previously this step was an optimization, but
-			// with the introduction of tuples and UniqueExprs, it is necessary to ensure that they use the same variable.
-			// Essentially, looking for pattern: (x=f(...), x)
-			// To compound the issue, the right side can be *x, etc. because of lvalue-returning functions
-			if ( UntypedExpr * assign = dynamic_cast< UntypedExpr * >( commaExpr->get_arg1() ) ) {
-				if ( CodeGen::isAssignment( InitTweak::getFunctionName( assign ) ) ) {
-					assert( assign->get_args().size() == 2 );
-					if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( assign->get_args().back() ) ) {
-						// first argument is assignable, so it must be an lvalue, so it should be legal to take its address.
-						retVals[appExpr] = assign->get_args().front();
-					}
-				}
-			}
-		}
-
-		std::list< Expression *>::iterator CallAdapter::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
-			Type *polyType = isPolyType( parmType, exprTyVars );
-			if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
-				std::string typeName = mangleType( polyType );
-				if ( seenTypes.count( typeName ) ) return arg;
-
-				arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
-				arg++;
-				arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
-				arg++;
-				if ( dynamic_cast< StructInstType* >( polyType ) ) {
-					if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
-						// zero-length arrays are forbidden by C, so don't pass offset for empty struct
-						if ( ! argBaseStructType->get_baseStruct()->get_members().empty() ) {
-							arg = appExpr->get_args().insert( arg, new OffsetPackExpr( argBaseStructType->clone() ) );
-							arg++;
-						}
-					} else {
-						SemanticError( argBaseType, "Cannot pass non-struct type for generic struct: " );
-					}
-				}
-
-				seenTypes.insert( typeName );
-			}
-			return arg;
-		}
-
-		std::list< Expression *>::iterator CallAdapter::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars ) {
-			assert( env );
-			std::list< Expression *>::iterator arg = appExpr->args.begin();
-			// pass size/align for type variables
-			// NOTE: This is iterating over a map. This means the sorting
-			// order of the keys changes behaviour, as the iteration order
-			// is visible outside the loop. - The order matches the orignal
-			// order because the vars have been renamed with numbers that,
-			// even when converted to strings, sort in the original order.
-			// (At least, that is the best explination I have.)
-			for ( std::pair<const std::string, TypeDecl::Data> const & tyParam : exprTyVars ) {
-				if ( !tyParam.second.isComplete ) continue;
-				Type *concrete = env->lookup( tyParam.first );
-				// If there is an unbound type variable, it should have detected already.
-				assertf( concrete, "Unbound type variable: %s in: %s",
-					toCString( tyParam.first ), toCString( *env ) );
-
-				arg = appExpr->get_args().insert( arg, new SizeofExpr( concrete->clone() ) );
-				arg++;
-				arg = appExpr->get_args().insert( arg, new AlignofExpr( concrete->clone() ) );
-				arg++;
-			} // for
-
-			// add size/align for generic types to parameter list
-			if ( ! appExpr->get_function()->result ) return arg;
-			FunctionType *funcType = getFunctionType( appExpr->get_function()->get_result() );
-			assert( funcType );
-
-			// Iterator over the original function arguments.
-			std::list< Expression* >::const_iterator fnArg;
-			// Names for generic types we've seen.
-			std::set< std::string > seenTypes;
-
-			// a polymorphic return type may need to be added to the argument list
-			if ( polyRetType ) {
-				Type *concRetType = replaceWithConcrete( polyRetType, env );
-				arg = passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
-				// Skip the return parameter in the argument list.
-				fnArg = arg + 1;
-			} else {
-				fnArg = arg;
-			}
-
-			// add type information args for presently unseen types in parameter list
-			std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin();
-			for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
-				Type * argType = (*fnArg)->get_result();
-				if ( ! argType ) continue;
-				arg = passArgTypeVars( appExpr, (*fnParm)->get_type(), argType, arg, exprTyVars, seenTypes );
-			}
-			return arg;
-		}
-
-		ObjectDecl *CallAdapter::makeTemporary( Type *type ) {
-			ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, type, 0 );
-			stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
-			return newObj;
-		}
-
-		Expression *CallAdapter::addRetParam( ApplicationExpr *appExpr, Type *retType ) {
-			// Create temporary to hold return value of polymorphic function and produce that temporary as a result
-			// using a comma expression.
-			assert( retType );
-
-			Expression * paramExpr = nullptr;
-			// try to use existing return value parameter if it exists, otherwise create a new temporary
-			if ( retVals.count( appExpr ) ) {
-				paramExpr = retVals[appExpr]->clone();
-			} else {
-				ObjectDecl *newObj = makeTemporary( retType->clone() );
-				paramExpr = new VariableExpr( newObj );
-			}
-			Expression * retExpr = paramExpr->clone();
-
-			// If the type of the temporary is not polymorphic, box temporary by taking its address;
-			// otherwise the temporary is already boxed and can be used directly.
-			if ( ! isPolyType( paramExpr->get_result(), scopeTyVars, env ) ) {
-				paramExpr = new AddressExpr( paramExpr );
-			} // if
-			// Add argument to function call.
-			appExpr->args.push_front( paramExpr );
-			// Build a comma expression to call the function and emulate a normal return.
-			CommaExpr *commaExpr = new CommaExpr( appExpr, retExpr );
-			commaExpr->env = appExpr->env;
-			appExpr->env = nullptr;
-			return commaExpr;
-		}
-
-		/// Replaces all the type parameters of a generic type with their concrete equivalents under the current environment
-		void replaceParametersWithConcrete( std::list< Expression* >& params, TypeSubstitution const * env ) {
-			for ( Expression * const param : params ) {
-				TypeExpr *paramType = dynamic_cast< TypeExpr* >( param );
-				assertf(paramType, "Aggregate parameters should be type expressions");
-				paramType->set_type( replaceWithConcrete( paramType->get_type(), env, false ) );
-			}
-		}
-
-		// See forward definition.
-		Type *replaceWithConcrete( Type *type, TypeSubstitution const * env, bool doClone ) {
-			assert( env );
-			if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
-				Type *concrete = env->lookup( typeInst->get_name() );
-				if ( concrete == 0 ) {
-					return typeInst;
-				} // if
-				return concrete;
-			} else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
-				if ( doClone ) {
-					structType = structType->clone();
-				}
-				replaceParametersWithConcrete( structType->get_parameters(), env );
-				return structType;
-			} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
-				if ( doClone ) {
-					unionType = unionType->clone();
-				}
-				replaceParametersWithConcrete( unionType->get_parameters(), env );
-				return unionType;
-			}
-			return type;
-		}
-
-		Expression *CallAdapter::addDynRetParam( ApplicationExpr *appExpr, Type *dynType ) {
-			Type *concrete = replaceWithConcrete( dynType, env );
-			// add out-parameter for return value
-			return addRetParam( appExpr, concrete );
-		}
-
-		Expression *CallAdapter::applyAdapter( ApplicationExpr *appExpr, FunctionType *function ) {
-			Expression *ret = appExpr;
-			if ( isDynRet( function, scopeTyVars ) ) {
-				ret = addRetParam( appExpr, function->returnVals.front()->get_type() );
-			} // if
-			std::string mangleName = mangleAdapterName( function, scopeTyVars );
-			std::string adapterName = makeAdapterName( mangleName );
-
-			// cast adaptee to void (*)(), since it may have any type inside a polymorphic function
-			Type * adapteeType = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
-			appExpr->get_args().push_front( new CastExpr( appExpr->function, adapteeType ) );
-			appExpr->set_function( new NameExpr( adapterName ) ); // xxx - result is never set on NameExpr
-
-			return ret;
-		}
-
-		// find instances of polymorphic type parameters
-		struct PolyFinder {
-			const TyVarMap * tyVars = nullptr;
-			bool found = false;
-
-			void previsit( TypeInstType * t ) {
-				if ( isPolyType( t, *tyVars ) ) {
-					found = true;
-				}
-			}
-		};
-
-		// true if there is an instance of a polymorphic type parameter in t
-		bool hasPolymorphism( Type * t, const TyVarMap &tyVars ) {
-			PassVisitor<PolyFinder> finder;
-			finder.pass.tyVars = &tyVars;
-			maybeAccept( t, finder );
-			return finder.pass.found;
-		}
-
-		/// cast parameters to polymorphic functions so that types are replaced with
-		/// void * if they are type parameters in the formal type.
-		/// this gets rid of warnings from gcc.
-		void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
-			// type contains polymorphism, but isn't exactly a polytype, in which case it
-			// has some real actual type (e.g. unsigned int) and casting to void * is wrong
-			if ( hasPolymorphism( formal, tyVars ) && ! isPolyType( formal, tyVars ) ) {
-				Type * newType = formal->clone();
-				newType = ScrubTyVars::scrub( newType, tyVars );
-				actual = new CastExpr( actual, newType );
-			} // if
-		}
-
-		void CallAdapter::boxParam( Expression *&arg, Type *param, const TyVarMap &exprTyVars ) {
-			assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() );
-			addCast( arg, param, exprTyVars );
-			if ( ! needsBoxing( param, arg->result, exprTyVars, env ) ) return;
-
-			if ( arg->get_lvalue() ) {
-				// argument expression may be CFA lvalue, but not C lvalue -- apply generalizedLvalue transformations.
-				// if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( arg ) ) {
-				// 	if ( dynamic_cast<ArrayType *>( varExpr->var->get_type() ) ){
-				// 		// temporary hack - don't box arrays, because &arr is not the same as &arr[0]
-				// 		return;
-				// 	}
-				// }
-				arg = generalizedLvalue( new AddressExpr( arg ) );
-				if ( ! ResolvExpr::typesCompatible( param, arg->get_result(), SymTab::Indexer() ) ) {
-					// silence warnings by casting boxed parameters when the actual type does not match up with the formal type.
-					arg = new CastExpr( arg, param->clone() );
-				}
-			} else {
-				// use type computed in unification to declare boxed variables
-				Type * newType = param->clone();
-				if ( env ) env->apply( newType );
-				ObjectDecl *newObj = makeTemporary( newType );
-				// TODO: is this right??? (Why wouldn't it be?)
-				newObj->get_type()->get_qualifiers() = Type::Qualifiers();
-				// TODO: why doesn't this just use initialization syntax?
-				// (Possibly to ensure code is run at the right time.)
-				UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
-				assign->get_args().push_back( new VariableExpr( newObj ) );
-				assign->get_args().push_back( arg );
-				stmtsToAddBefore.push_back( new ExprStmt( assign ) );
-				arg = new AddressExpr( new VariableExpr( newObj ) );
-			} // if
-		}
-
-		void CallAdapter::boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars ) {
-			for ( DeclarationWithType * param : function->parameters ) {
-				assertf( arg != appExpr->args.end(), "boxParams: missing argument for param %s to %s in %s", toString( param ).c_str(), toString( function ).c_str(), toString( appExpr ).c_str() );
-				boxParam( *arg, param->get_type(), exprTyVars );
-				++arg;
-			} // for
-		}
-
-		void CallAdapter::addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars ) {
-			for ( TypeDecl * const tyVar : functionType->forall ) {
-				for ( DeclarationWithType * const assert : tyVar->assertions ) {
-					InferredParams::const_iterator inferParam = appExpr->inferParams.find( assert->get_uniqueId() );
-					assertf( inferParam != appExpr->inferParams.end(), "addInferredParams missing inferred parameter: %s in: %s", toString( assert ).c_str(), toString( appExpr ).c_str() );
-					Expression *newExpr = inferParam->second.expr->clone();
-					boxParam( newExpr, assert->get_type(), tyVars );
-					arg = appExpr->get_args().insert( arg, newExpr );
-					++arg;
-				} // for
-			} // for
-		}
-
-		void makeRetParm( FunctionType *funcType ) {
-			DeclarationWithType *retParm = funcType->returnVals.front();
-
-			// make a new parameter that is a pointer to the type of the old return value
-			retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) );
-			funcType->get_parameters().push_front( retParm );
-
-			// we don't need the return value any more
-			funcType->get_returnVals().clear();
-		}
-
-		FunctionType *makeAdapterType( FunctionType const *adaptee, const TyVarMap &tyVars ) {
-			// actually make the adapter type
-			FunctionType *adapter = adaptee->clone();
-			if ( isDynRet( adapter, tyVars ) ) {
-				makeRetParm( adapter );
-			} // if
-			adapter->get_parameters().push_front( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 ) );
-			return adapter;
-		}
-
-		Expression *makeAdapterArg(
-				DeclarationWithType *param,
-				DeclarationWithType const *arg,
-				DeclarationWithType const *realParam,
-				const TyVarMap &tyVars ) {
-			assert( param );
-			assert( arg );
-			if ( isPolyType( realParam->get_type(), tyVars )
-					&& ! isPolyType( arg->get_type() ) ) {
-				UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
-				deref->args.push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
-				deref->result = arg->get_type()->clone();
-				return deref;
-			} // if
-			return new VariableExpr( param );
-		}
-
-		void addAdapterParams(
-				ApplicationExpr *adapteeApp,
-				std::list< DeclarationWithType *>::const_iterator arg,
-				std::list< DeclarationWithType *>::const_iterator param,
-				std::list< DeclarationWithType *>::const_iterator paramEnd,
-				std::list< DeclarationWithType *>::const_iterator realParam,
-				const TyVarMap &tyVars ) {
-			UniqueName paramNamer( "_p" );
-			for ( ; param != paramEnd; ++param, ++arg, ++realParam ) {
-				if ( (*param)->get_name() == "" ) {
-					(*param)->set_name( paramNamer.newName() );
-					(*param)->set_linkage( LinkageSpec::C );
-				} // if
-				adapteeApp->get_args().push_back( makeAdapterArg( *param, *arg, *realParam, tyVars ) );
-			} // for
-		}
-
-		FunctionDecl *CallAdapter::makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
-			FunctionType *adapterType = makeAdapterType( adaptee, tyVars );
-			adapterType = ScrubTyVars::scrub( adapterType, tyVars );
-			DeclarationWithType *adapteeDecl = adapterType->get_parameters().front();
-			adapteeDecl->set_name( "_adaptee" );
-			// do not carry over attributes to real type parameters/return values
-			for ( DeclarationWithType * dwt : realType->parameters ) {
-				deleteAll( dwt->get_type()->attributes );
-				dwt->get_type()->attributes.clear();
-			}
-			for ( DeclarationWithType * dwt : realType->returnVals ) {
-				deleteAll( dwt->get_type()->attributes );
-				dwt->get_type()->attributes.clear();
-			}
-			ApplicationExpr *adapteeApp = new ApplicationExpr( new CastExpr( new VariableExpr( adapteeDecl ), new PointerType( Type::Qualifiers(), realType ) ) );
-			Statement *bodyStmt;
-
-			for ( auto tys : group_iterate( realType->forall, adapterType->forall, adaptee->forall ) ) {
-				TypeDecl * tyArg = std::get<0>( tys );
-				TypeDecl * tyParam = std::get<1>( tys );
-				TypeDecl * realTyParam = std::get<2>( tys );
-				for ( auto asserts : group_iterate( tyArg->assertions, tyParam->assertions, realTyParam->assertions ) ) {
-					DeclarationWithType * assertArg = std::get<0>( asserts );
-					DeclarationWithType * assertParam = std::get<1>( asserts );
-					DeclarationWithType * realAssertParam = std::get<2>( asserts );
-					adapteeApp->args.push_back( makeAdapterArg( assertParam, assertArg, realAssertParam, tyVars ) );
-				} // for
-			} // for
-
-			std::list< DeclarationWithType *>::const_iterator arg = realType->parameters.begin();
-			std::list< DeclarationWithType *>::const_iterator param = adapterType->parameters.begin();
-			std::list< DeclarationWithType *>::const_iterator realParam = adaptee->parameters.begin();
-			param++;		// skip adaptee parameter in the adapter type
-			if ( realType->get_returnVals().empty() ) {
-				// void return
-				addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
-				bodyStmt = new ExprStmt( adapteeApp );
-			} else if ( isDynType( adaptee->returnVals.front()->get_type(), tyVars ) ) {
-				// return type T
-				if ( (*param)->get_name() == "" ) {
-					(*param)->set_name( "_ret" );
-					(*param)->set_linkage( LinkageSpec::C );
-				} // if
-				UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
-				UntypedExpr *deref = UntypedExpr::createDeref( new CastExpr( new VariableExpr( *param++ ), new PointerType( Type::Qualifiers(), realType->get_returnVals().front()->get_type()->clone() ) ) );
-				assign->get_args().push_back( deref );
-				addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
-				assign->get_args().push_back( adapteeApp );
-				bodyStmt = new ExprStmt( assign );
-			} else {
-				// adapter for a function that returns a monomorphic value
-				addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
-				bodyStmt = new ReturnStmt( adapteeApp );
-			} // if
-			CompoundStmt *adapterBody = new CompoundStmt();
-			adapterBody->get_kids().push_back( bodyStmt );
-			std::string adapterName = makeAdapterName( mangleName );
-			return new FunctionDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, adapterType, adapterBody );
-		}
-
-		void CallAdapter::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
-			// collect a list of function types passed as parameters or implicit parameters (assertions)
-			std::list<FunctionType const *> functions;
-			for ( TypeDecl * const tyVar : functionType->get_forall() ) {
-				for ( DeclarationWithType * const assert : tyVar->get_assertions() ) {
-					findFunction( assert->get_type(), functions, exprTyVars, needsAdapter );
-				} // for
-			} // for
-			for ( DeclarationWithType * const arg : functionType->get_parameters() ) {
-				findFunction( arg->get_type(), functions, exprTyVars, needsAdapter );
-			} // for
-
-			// parameter function types for which an appropriate adapter has been generated.  we cannot use the types
-			// after applying substitutions, since two different parameter types may be unified to the same type
-			std::set< std::string > adaptersDone;
-
-			for ( FunctionType const * const funType : functions ) {
-				std::string mangleName = SymTab::Mangler::mangle( funType );
-
-				// only attempt to create an adapter or pass one as a parameter if we haven't already done so for this
-				// pre-substitution parameter function type.
-				// The second part of the insert result is "is the value new".
-				if ( !adaptersDone.insert( mangleName ).second ) continue;
-
-				// Apply substitution to type variables to figure out what the adapter's type should look like.
-				assert( env );
-				FunctionType *realType = funType->clone();
-				env->apply( realType );
-				mangleName = SymTab::Mangler::mangle( realType );
-				mangleName += makePolyMonoSuffix( funType, exprTyVars );
-
-				typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
-				AdapterIter adapter = adapters.find( mangleName );
-				if ( adapter == adapters.end() ) {
-					// Adapter has not been created yet in the current scope, so define it.
-					FunctionDecl *newAdapter = makeAdapter( funType, realType, mangleName, exprTyVars );
-					std::pair< AdapterIter, bool > answer = adapters.insert( mangleName, newAdapter );
-					adapter = answer.first;
-					stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) );
-				} // if
-				assert( adapter != adapters.end() );
-
-				// Add the appropriate adapter as a parameter.
-				appExpr->args.push_front( new VariableExpr( adapter->second ) );
-			} // for
-		} // passAdapters
-
-		Expression *makeIncrDecrExpr( ApplicationExpr *appExpr, Type *polyType, bool isIncr ) {
-			NameExpr *opExpr = new NameExpr( ( isIncr ) ? "?+=?" : "?-=?" );
-			UntypedExpr *addAssign = new UntypedExpr( opExpr );
-			if ( AddressExpr *address = dynamic_cast< AddressExpr *>( appExpr->get_args().front() ) ) {
-				addAssign->get_args().push_back( address->get_arg() );
-			} else {
-				addAssign->get_args().push_back( appExpr->get_args().front() );
-			} // if
-			addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType ) ) ) );
-			addAssign->set_result( appExpr->get_result()->clone() );
-			if ( appExpr->get_env() ) {
-				addAssign->set_env( appExpr->get_env() );
-				appExpr->set_env( 0 );
-			} // if
-			appExpr->get_args().clear();
-			delete appExpr;
-			return addAssign;
-		}
-
-		Expression *CallAdapter::handleIntrinsics( ApplicationExpr *appExpr ) {
-			if ( VariableExpr *varExpr = dynamic_cast< VariableExpr *>( appExpr->function ) ) {
-				if ( varExpr->var->linkage == LinkageSpec::Intrinsic ) {
-					if ( varExpr->var->name == "?[?]" ) {
-						assert( appExpr->result );
-						assert( appExpr->get_args().size() == 2 );
-						Type *baseType1 = isPolyPtr( appExpr->args.front()->result, scopeTyVars, env );
-						Type *baseType2 = isPolyPtr( appExpr->args.back()->result, scopeTyVars, env );
-						assert( ! baseType1 || ! baseType2 ); // the arguments cannot both be polymorphic pointers
-						UntypedExpr *ret = 0;
-						if ( baseType1 || baseType2 ) { // one of the arguments is a polymorphic pointer
-							ret = new UntypedExpr( new NameExpr( "?+?" ) );
-						} // if
-						if ( baseType1 ) {
-							UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
-							multiply->get_args().push_back( appExpr->get_args().back() );
-							multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
-							ret->get_args().push_back( appExpr->get_args().front() );
-							ret->get_args().push_back( multiply );
-						} else if ( baseType2 ) {
-							UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
-							multiply->get_args().push_back( appExpr->get_args().front() );
-							multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
-							ret->get_args().push_back( multiply );
-							ret->get_args().push_back( appExpr->get_args().back() );
-						} // if
-						if ( baseType1 || baseType2 ) {
-							delete ret->get_result();
-							ret->set_result( appExpr->get_result()->clone() );
-							if ( appExpr->get_env() ) {
-								ret->set_env( appExpr->get_env() );
-								appExpr->set_env( 0 );
-							} // if
-							appExpr->get_args().clear();
-							delete appExpr;
-							return ret;
-						} // if
-					} else if ( varExpr->get_var()->get_name() == "*?" ) {
-						assert( appExpr->result );
-						assert( ! appExpr->get_args().empty() );
-						if ( isPolyType( appExpr->get_result(), scopeTyVars, env ) ) {
-							// remove dereference from polymorphic types since they are boxed.
-							Expression *ret = appExpr->get_args().front();
-							// fix expr type to remove pointer
-							delete ret->get_result();
-							ret->set_result( appExpr->get_result()->clone() );
-							if ( appExpr->get_env() ) {
-								ret->set_env( appExpr->get_env() );
-								appExpr->set_env( 0 );
-							} // if
-							appExpr->get_args().clear();
-							delete appExpr;
-							return ret;
-						} // if
-					} else if ( varExpr->get_var()->get_name() == "?++" || varExpr->get_var()->get_name() == "?--" ) {
-						assert( appExpr->result );
-						assert( appExpr->get_args().size() == 1 );
-						if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
-							Type *tempType = appExpr->get_result()->clone();
-							if ( env ) {
-								env->apply( tempType );
-							} // if
-							ObjectDecl *newObj = makeTemporary( tempType );
-							VariableExpr *tempExpr = new VariableExpr( newObj );
-							UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
-							assignExpr->get_args().push_back( tempExpr->clone() );
-							if ( AddressExpr *address = dynamic_cast< AddressExpr *>( appExpr->get_args().front() ) ) {
-								assignExpr->get_args().push_back( address->get_arg()->clone() );
-							} else {
-								assignExpr->get_args().push_back( appExpr->get_args().front()->clone() );
-							} // if
-							CommaExpr *firstComma = new CommaExpr( assignExpr, makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "?++" ) );
-							return new CommaExpr( firstComma, tempExpr );
-						} // if
-					} else if ( varExpr->get_var()->get_name() == "++?" || varExpr->get_var()->get_name() == "--?" ) {
-						assert( appExpr->result );
-						assert( appExpr->get_args().size() == 1 );
-						if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
-							return makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "++?" );
-						} // if
-					} else if ( varExpr->get_var()->get_name() == "?+?" || varExpr->get_var()->get_name() == "?-?" ) {
-						assert( appExpr->result );
-						assert( appExpr->get_args().size() == 2 );
-						Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
-						Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_result(), scopeTyVars, env );
-						if ( baseType1 && baseType2 ) {
-							UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) );
-							divide->get_args().push_back( appExpr );
-							divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
-							divide->set_result( appExpr->get_result()->clone() );
-							if ( appExpr->get_env() ) {
-								divide->set_env( appExpr->get_env() );
-								appExpr->set_env( 0 );
-							} // if
-							return divide;
-						} else if ( baseType1 ) {
-							UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
-							multiply->get_args().push_back( appExpr->get_args().back() );
-							multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
-							appExpr->get_args().back() = multiply;
-						} else if ( baseType2 ) {
-							UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
-							multiply->get_args().push_back( appExpr->get_args().front() );
-							multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
-							appExpr->get_args().front() = multiply;
-						} // if
-					} else if ( varExpr->get_var()->get_name() == "?+=?" || varExpr->get_var()->get_name() == "?-=?" ) {
-						assert( appExpr->result );
-						assert( appExpr->get_args().size() == 2 );
-						Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env );
-						if ( baseType ) {
-							UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
-							multiply->get_args().push_back( appExpr->get_args().back() );
-							multiply->get_args().push_back( new SizeofExpr( baseType->clone() ) );
-							appExpr->get_args().back() = multiply;
-						} // if
-					} // if
-					return appExpr;
-				} // if
-			} // if
-			return 0;
-		}
-
-		Expression *CallAdapter::postmutate( ApplicationExpr *appExpr ) {
-			// std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl;
-			// for ( auto tyVar : scopeTyVars ) {
-			// 	std::cerr << tyVar.first << " ";
-			// }
-			// std::cerr << "\n";
-
-			assert( appExpr->function->result );
-			FunctionType * function = getFunctionType( appExpr->function->result );
-			assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
-
-			if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
-				return newExpr;
-			} // if
-
-			Expression *ret = appExpr;
-			// Save iterator to the first original parameter (works with lists).
-			std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
-
-			TyVarMap exprTyVars( TypeDecl::Data{} );
-			makeTyVarMap( function, exprTyVars ); // xxx - should this take into account the variables already bound in scopeTyVars (i.e. remove them from exprTyVars?)
-			ReferenceToType *dynRetType = isDynRet( function, exprTyVars );
-
-			// std::cerr << function << std::endl;
-			// std::cerr << "scopeTyVars: ";
-			// printTyVarMap( std::cerr, scopeTyVars );
-			// std::cerr << "exprTyVars: ";
-			// printTyVarMap( std::cerr, exprTyVars );
-			// std::cerr << "env: " << *env << std::endl;
-			// std::cerr << needsAdapter( function, scopeTyVars ) << ! needsAdapter( function, exprTyVars) << std::endl;
-
-			// NOTE: addDynRetParam needs to know the actual (generated) return type so it can make a temp variable, so pass the result type from the appExpr
-			// passTypeVars needs to know the program-text return type (i.e. the distinction between _conc_T30 and T3(int))
-			// concRetType may not be a good name in one or both of these places. A more appropriate name change is welcome.
-			if ( dynRetType ) {
-				// std::cerr << "dynRetType: " << dynRetType << std::endl;
-				Type *concRetType = appExpr->get_result()->isVoid() ? nullptr : appExpr->get_result();
-				ret = addDynRetParam( appExpr, concRetType ); // xxx - used to use dynRetType instead of concRetType
-			} else if ( needsAdapter( function, scopeTyVars ) && ! needsAdapter( function, exprTyVars) ) { // xxx - exprTyVars is used above...?
-				// xxx - the ! needsAdapter check may be incorrect. It seems there is some situation where an adapter is applied where it shouldn't be, and this fixes it for some cases. More investigation is needed.
-
-				// std::cerr << "needs adapter: ";
-				// printTyVarMap( std::cerr, scopeTyVars );
-				// std::cerr << *env << std::endl;
-				// change the application so it calls the adapter rather than the passed function
-				ret = applyAdapter( appExpr, function );
-			} // if
-
-			Type *concRetType = replaceWithConcrete( dynRetType, env );
-			std::list< Expression *>::iterator arg =
-				passTypeVars( appExpr, concRetType, exprTyVars ); // xxx - used to use dynRetType instead of concRetType; this changed so that the correct type paramaters are passed for return types (it should be the concrete type's parameters, not the formal type's)
-			addInferredParams( appExpr, arg, function, exprTyVars );
-
-			// This needs to point at the original first argument.
-			boxParams( appExpr, paramBegin, function, exprTyVars );
-
-			passAdapters( appExpr, function, exprTyVars );
-
-			return ret;
-		}
-
-		bool isPolyDeref( UntypedExpr const * expr, TyVarMap const & scopeTyVars, TypeSubstitution const * env ) {
-			if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) {
-				if ( auto name = dynamic_cast<NameExpr const *>( expr->function ) ) {
-					if ( name->name == "*?" ) {
-						return true;
-					} // if
-				} // if
-			} // if
-			return false;
-		}
-
-		Expression * CallAdapter::postmutate( UntypedExpr *expr ) {
-			if ( isPolyDeref( expr, scopeTyVars, env ) ) {
-				Expression *ret = expr->args.front();
-				expr->args.clear();
-				delete expr;
-				return ret;
-			}
-			return expr;
-		}
-
-		void CallAdapter::premutate( AddressExpr * ) { visit_children = false; }
-
-		Expression * CallAdapter::postmutate( AddressExpr * addrExpr ) {
-			assert( addrExpr->arg->result && ! addrExpr->arg->result->isVoid() );
-
-			bool needs = false;
-			if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->arg ) ) {
-				if ( isPolyDeref( expr, scopeTyVars, env ) ) {
-					if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->args.front() ) ) {
-						assert( appExpr->function->result );
-						FunctionType *function = getFunctionType( appExpr->function->result );
-						assert( function );
-						needs = needsAdapter( function, scopeTyVars );
-					} // if
-				} // if
-			} // if
-			// isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
-			// out of the if condition.
-			addrExpr->arg = addrExpr->arg->acceptMutator( *visitor );
-			// ... but must happen after mutate, since argument might change (e.g. intrinsic *?, ?[?]) - re-evaluate above comment
-			bool polytype = isPolyType( addrExpr->arg->result, scopeTyVars, env );
-			if ( polytype || needs ) {
-				Expression *ret = addrExpr->arg;
-				delete ret->result;
-				ret->result = addrExpr->result->clone();
-				addrExpr->arg = nullptr;
-				delete addrExpr;
-				return ret;
-			} else {
-				return addrExpr;
-			} // if
-		}
-
-		void CallAdapter::premutate( ReturnStmt *returnStmt ) {
-			if ( retval && returnStmt->expr ) {
-				assert( returnStmt->expr->result && ! returnStmt->expr->result->isVoid() );
-				delete returnStmt->expr;
-				returnStmt->expr = nullptr;
-			} // if
-		}
-
-		void CallAdapter::premutate( PointerType *pointerType ) {
-			GuardScope( scopeTyVars );
-			makeTyVarMap( pointerType, scopeTyVars );
-		}
-
-		void CallAdapter::premutate( FunctionType *functionType ) {
-			GuardScope( scopeTyVars );
-			makeTyVarMap( functionType, scopeTyVars );
-		}
-
-		void CallAdapter::beginScope() {
-			adapters.beginScope();
-		}
-
-		void CallAdapter::endScope() {
-			adapters.endScope();
-		}
-
-////////////////////////////////////////// DeclAdapter //////////////////////////////////////////
-
-		void DeclAdapter::addAdapters( FunctionType *functionType ) {
-			std::list< FunctionType const *> functions;
-			for ( DeclarationWithType * const arg : functionType->parameters ) {
-				Type *orig = arg->get_type();
-				findAndReplaceFunction( orig, functions, scopeTyVars, needsAdapter );
-				arg->set_type( orig );
-			}
-			std::set< std::string > adaptersDone;
-			for ( FunctionType const * const funType : functions ) {
-				std::string mangleName = mangleAdapterName( funType, scopeTyVars );
-				if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
-					std::string adapterName = makeAdapterName( mangleName );
-					// adapter may not be used in body, pass along with unused attribute.
-					functionType->parameters.push_front(
-						new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( funType, scopeTyVars ) ), 0, { new Attribute( "unused" ) } ) );
-					adaptersDone.insert( adaptersDone.begin(), mangleName );
-				}
-			}
-		}
-
-		DeclarationWithType * DeclAdapter::postmutate( FunctionDecl *functionDecl ) {
-			FunctionType * ftype = functionDecl->type;
-			if ( ! ftype->returnVals.empty() && functionDecl->statements ) {
-				// intrinsic functions won't be using the _retval so no need to generate it.
-				if ( functionDecl->linkage != LinkageSpec::Intrinsic && !isPrefix( functionDecl->name, "_thunk" ) && ! isPrefix( functionDecl->name, "_adapter" ) ) { // xxx - remove check for prefix once thunks properly use ctor/dtors
-					assert( ftype->returnVals.size() == 1 );
-					DeclarationWithType * retval = ftype->returnVals.front();
-					if ( retval->name == "" ) {
-						retval->name = "_retval";
-					}
-					functionDecl->statements->kids.push_front( new DeclStmt( retval ) );
-					DeclarationWithType * newRet = retval->clone(); // for ownership purposes
-					ftype->returnVals.front() = newRet;
-				}
-			}
-			// errors should have been caught by this point, remove initializers from parameters to allow correct codegen of default arguments
-			for ( Declaration * param : functionDecl->type->parameters ) {
-				if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( param ) ) {
-					delete obj->init;
-					obj->init = nullptr;
-				}
-			}
-			return functionDecl;
-		}
-
-		void DeclAdapter::premutate( StructDecl * ) {
-			// prevent tyVars from leaking into containing scope
-			GuardScope( scopeTyVars );
-		}
-
-		void DeclAdapter::premutate( UnionDecl * ) {
-			// prevent tyVars from leaking into containing scope
-			GuardScope( scopeTyVars );
-		}
-
-		void DeclAdapter::premutate( TraitDecl * ) {
-			// prevent tyVars from leaking into containing scope
-			GuardScope( scopeTyVars );
-		}
-
-		void DeclAdapter::premutate( TypeDecl *typeDecl ) {
-			addToTyVarMap( typeDecl, scopeTyVars );
-		}
-
-		void DeclAdapter::premutate( PointerType *pointerType ) {
-			GuardScope( scopeTyVars );
-			makeTyVarMap( pointerType, scopeTyVars );
-		}
-
-		void DeclAdapter::premutate( FunctionType *funcType ) {
-			GuardScope( scopeTyVars );
-			makeTyVarMap( funcType, scopeTyVars );
-
-			// move polymorphic return type to parameter list
-			if ( isDynRet( funcType ) ) {
-				ObjectDecl *ret = strict_dynamic_cast< ObjectDecl* >( funcType->get_returnVals().front() );
-				ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
-				funcType->get_parameters().push_front( ret );
-				funcType->get_returnVals().pop_front();
-				ret->set_init( nullptr ); // xxx - memory leak?
-			}
-
-			// add size/align and assertions for type parameters to parameter list
-			std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin();
-			std::list< DeclarationWithType *> inferredParams;
-			// size/align/offset parameters may not be used in body, pass along with unused attribute.
-			ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0,
-			                   { new Attribute( "unused" ) } );
-			ObjectDecl newPtr( "", Type::StorageClasses(), LinkageSpec::C, 0,
-			                   new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
-			for ( TypeDecl * const tyParam : funcType->get_forall() ) {
-				ObjectDecl *sizeParm, *alignParm;
-				// add all size and alignment parameters to parameter list
-				if ( tyParam->isComplete() ) {
-					TypeInstType parmType( Type::Qualifiers(), tyParam->get_name(), tyParam );
-					std::string parmName = mangleType( &parmType );
-
-					sizeParm = newObj.clone();
-					sizeParm->set_name( sizeofName( parmName ) );
-					last = funcType->get_parameters().insert( last, sizeParm );
-					++last;
-
-					alignParm = newObj.clone();
-					alignParm->set_name( alignofName( parmName ) );
-					last = funcType->get_parameters().insert( last, alignParm );
-					++last;
-				}
-				// move all assertions into parameter list
-				for ( DeclarationWithType * const assert : tyParam->get_assertions() ) {
-					// assertion parameters may not be used in body, pass along with unused attribute.
-					assert->get_attributes().push_back( new Attribute( "unused" ) );
-					inferredParams.push_back( assert );
-				}
-				tyParam->get_assertions().clear();
-			}
-
-			// add size/align for generic parameter types to parameter list
-			std::set< std::string > seenTypes; // sizeofName for generic types we've seen
-			for ( DeclarationWithType * const fnParam : funcType->get_parameters() ) {
-				Type *polyType = isPolyType( fnParam->get_type(), scopeTyVars );
-				if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
-					std::string typeName = mangleType( polyType );
-					if ( seenTypes.count( typeName ) ) continue;
-
-					ObjectDecl *sizeParm, *alignParm, *offsetParm;
-					sizeParm = newObj.clone();
-					sizeParm->set_name( sizeofName( typeName ) );
-					last = funcType->get_parameters().insert( last, sizeParm );
-					++last;
-
-					alignParm = newObj.clone();
-					alignParm->set_name( alignofName( typeName ) );
-					last = funcType->get_parameters().insert( last, alignParm );
-					++last;
-
-					if ( StructInstType *polyBaseStruct = dynamic_cast< StructInstType* >( polyType ) ) {
-						// NOTE zero-length arrays are illegal in C, so empty structs have no offset array
-						if ( ! polyBaseStruct->get_baseStruct()->get_members().empty() ) {
-							offsetParm = newPtr.clone();
-							offsetParm->set_name( offsetofName( typeName ) );
-							last = funcType->get_parameters().insert( last, offsetParm );
-							++last;
-						}
-					}
-					seenTypes.insert( typeName );
-				}
-			}
-
-			// splice assertion parameters into parameter list
-			funcType->get_parameters().splice( last, inferredParams );
-			addAdapters( funcType );
-		}
-
-////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////
-
-		PolyGenericCalculator::PolyGenericCalculator()
-			: knownLayouts(), knownOffsets(), bufNamer( "_buf" ) {}
-
-		void PolyGenericCalculator::beginTypeScope( Type *ty ) {
-			GuardScope( scopeTyVars );
-			makeTyVarMap( ty, scopeTyVars );
-		}
-
-		void PolyGenericCalculator::beginGenericScope() {
-			GuardScope( *this );
-			// We expect the first function type see to be the type relating to this scope
-			// but any further type is probably some unrelated function pointer
-			// keep track of which is the first
-			GuardValue( expect_func_type );
-			expect_func_type = true;
-		}
-
-		void PolyGenericCalculator::premutate( ObjectDecl *objectDecl ) {
-			beginTypeScope( objectDecl->get_type() );
-		}
-
-		void PolyGenericCalculator::premutate( FunctionDecl *functionDecl ) {
-			beginGenericScope();
-
-			beginTypeScope( functionDecl->get_functionType() );
-		}
-
-		void PolyGenericCalculator::premutate( TypedefDecl *typedefDecl ) {
-			assert(false);
-			beginTypeScope( typedefDecl->get_base() );
-		}
-
-		void PolyGenericCalculator::premutate( TypeDecl * typeDecl ) {
-			addToTyVarMap( typeDecl, scopeTyVars );
-		}
-
-		Declaration * PolyGenericCalculator::postmutate( TypeDecl *typeDecl ) {
-			if ( Type * base = typeDecl->base ) {
-				// add size/align variables for opaque type declarations
-				TypeInstType inst( Type::Qualifiers(), typeDecl->name, typeDecl );
-				std::string typeName = mangleType( &inst );
-				Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-
-				ObjectDecl * sizeDecl = ObjectDecl::newObject( sizeofName( typeName ), layoutType, new SingleInit( new SizeofExpr( base->clone() ) ) );
-				ObjectDecl * alignDecl = ObjectDecl::newObject( alignofName( typeName ), layoutType->clone(), new SingleInit( new AlignofExpr( base->clone() ) ) );
-
-				// ensure that the initializing sizeof/alignof exprs are properly mutated
-				sizeDecl->acceptMutator( *visitor );
-				alignDecl->acceptMutator( *visitor );
-
-				// can't use makeVar, because it inserts into stmtsToAdd and TypeDecls can occur at global scope
-				declsToAddAfter.push_back( alignDecl );
-				// replace with sizeDecl
-				return sizeDecl;
-			}
-			return typeDecl;
-		}
-
-		void PolyGenericCalculator::premutate( PointerType *pointerType ) {
-			beginTypeScope( pointerType );
-		}
-
-		void PolyGenericCalculator::premutate( FunctionType *funcType ) {
-			beginTypeScope( funcType );
-
-			GuardValue( expect_func_type );
-
-			if(!expect_func_type) {
-				// If this is the first function type we see
-				// Then it's the type of the declaration and we care about it
-				GuardScope( *this );
-			}
-
-			// The other functions type we will see in this scope are probably functions parameters
-			// they don't help us with the layout and offsets so don't mark them as known in this scope
-			expect_func_type = false;
-
-			// make sure that any type information passed into the function is accounted for
-			for ( DeclarationWithType * const fnParam : funcType->get_parameters() ) {
-				// condition here duplicates that in DeclAdapter::mutate( FunctionType* )
-				Type *polyType = isPolyType( fnParam->get_type(), scopeTyVars );
-				if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
-					knownLayouts.insert( mangleType( polyType ) );
-				}
-			}
-		}
-
-		/// converts polymorphic type T into a suitable monomorphic representation, currently: __attribute__((aligned(8)) char[size_T]
-		Type * polyToMonoType( Type const * declType ) {
-			Type * charType = new BasicType( Type::Qualifiers(), BasicType::Kind::Char);
-			Expression * size = new NameExpr( sizeofName( mangleType(declType) ) );
-			Attribute * aligned = new Attribute( "aligned", std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } );
-			return new ArrayType( Type::Qualifiers(), charType, size,
-				true, false, std::list<Attribute *>{ aligned } );
-		}
-
-		void PolyGenericCalculator::mutateMembers( AggregateDecl * aggrDecl ) {
-			std::set< std::string > genericParams;
-			for ( TypeDecl * td : aggrDecl->parameters ) {
-				genericParams.insert( td->name );
-			}
-			for ( Declaration * decl : aggrDecl->members ) {
-				if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( decl ) ) {
-					Type * ty = replaceTypeInst( field->type, env );
-					if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
-						// do not try to monomorphize generic parameters
-						if ( scopeTyVars.contains( typeInst->get_name() ) && ! genericParams.count( typeInst->name ) ) {
-							// polymorphic aggregate members should be converted into monomorphic members.
-							// Using char[size_T] here respects the expected sizing rules of an aggregate type.
-							Type * newType = polyToMonoType( field->type );
-							delete field->type;
-							field->type = newType;
-						}
-					}
-				}
-			}
-		}
-
-		void PolyGenericCalculator::premutate( StructDecl * structDecl ) {
-			mutateMembers( structDecl );
-		}
-
-		void PolyGenericCalculator::premutate( UnionDecl * unionDecl ) {
-			mutateMembers( unionDecl );
-		}
-
-		void PolyGenericCalculator::premutate( DeclStmt *declStmt ) {
-			if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
-				if ( findGeneric( objectDecl->get_type() ) ) {
-					// change initialization of a polymorphic value object to allocate via a VLA
-					// (alloca was previously used, but can't be safely used in loops)
-					ObjectDecl *newBuf = ObjectDecl::newObject( bufNamer.newName(), polyToMonoType( objectDecl->type ), nullptr );
-					stmtsToAddBefore.push_back( new DeclStmt( newBuf ) );
-
-					// if the object has a cleanup attribute, the cleanup should be on the buffer, not the pointer
-					auto matchAndMove = [newBuf](Attribute * attr){
-						if(attr->name == "cleanup") {
-							newBuf->attributes.push_back(attr);
-							return true;
-						}
-						return false;
-					};
-
-					objectDecl->attributes.remove_if(matchAndMove);
-
-					delete objectDecl->get_init();
-					objectDecl->set_init( new SingleInit( new VariableExpr( newBuf ) ) );
-				}
-			}
-		}
-
-		/// Checks if memberDecl matches the decl from an aggregate.
-		bool isMember( DeclarationWithType *memberDecl, Declaration * decl ) {
-			if ( memberDecl->get_name() != decl->get_name() )
-				return false;
-
-			if ( memberDecl->get_name().empty() ) {
-				// Plan-9 Field: match on unique_id.
-				return ( memberDecl->get_uniqueId() == decl->get_uniqueId() );
-			}
-
-			DeclarationWithType *declWithType = strict_dynamic_cast< DeclarationWithType* >( decl );
-
-			if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty() ) {
-				// Tuple-Element Field: expect neither had mangled name; accept match on simple name (like field_2) only.
-				assert( memberDecl->get_mangleName().empty() && declWithType->get_mangleName().empty() );
-				return true;
-			}
-
-			// Ordinary Field: Use full name to accommodate overloading.
-			return ( memberDecl->get_mangleName() == declWithType->get_mangleName() );
-		}
-
-		/// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present
-		long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) {
-			for ( auto pair : enumerate( baseDecls ) ) {
-				if ( isMember( memberDecl, pair.val ) ) {
-					return pair.idx;
-				}
-			}
-			return -1;
-		}
-
-		/// Returns an index expression into the offset array for a type
-		Expression *makeOffsetIndex( Type const *objectType, long i ) {
-			ConstantExpr *fieldIndex = new ConstantExpr( Constant::from_ulong( i ) );
-			UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
-			fieldOffset->get_args().push_back( new NameExpr( offsetofName( mangleType( objectType ) ) ) );
-			fieldOffset->get_args().push_back( fieldIndex );
-			return fieldOffset;
-		}
-
-		Expression *PolyGenericCalculator::postmutate( MemberExpr *memberExpr ) {
-			// only mutate member expressions for polymorphic types
-			int tyDepth;
-			Type *objectType = hasPolyBase( memberExpr->aggregate->result, scopeTyVars, &tyDepth );
-			if ( ! objectType ) return memberExpr;
-			findGeneric( objectType ); // ensure layout for this type is available
-
-			// replace member expression with dynamically-computed layout expression
-			Expression *newMemberExpr = nullptr;
-			if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
-				// look up offset index
-				long i = findMember( memberExpr->member, structType->baseStruct->members );
-				if ( i == -1 ) return memberExpr;
-
-				// replace member expression with pointer to base plus offset
-				UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
-				Expression * aggr = memberExpr->aggregate->clone();
-				delete aggr->env; // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
-				aggr->env = nullptr;
-				fieldLoc->get_args().push_back( aggr );
-				fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
-				fieldLoc->set_result( memberExpr->result->clone() );
-				newMemberExpr = fieldLoc;
-			} else if ( dynamic_cast< UnionInstType* >( objectType ) ) {
-				// union members are all at offset zero, so just use the aggregate expr
-				Expression * aggr = memberExpr->aggregate->clone();
-				delete aggr->env; // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
-				aggr->env= nullptr;
-				newMemberExpr = aggr;
-				newMemberExpr->result = memberExpr->result->clone();
-			} else return memberExpr;
-			assert( newMemberExpr );
-
-			// Must apply the generic substitution to the member type to handle cases where the member is a generic parameter substituted by a known concrete type, e.g.
-			//   forall(otype T) struct Box { T x; }
-			//   forall(otype T) f() {
-			//     Box(T *) b; b.x;
-			//   }
-			// TODO: memberExpr->result should be exactly memberExpr->member->get_type() after substitution, so it doesn't seem like it should be necessary to apply the substitution manually. For some reason this is not currently the case. This requires more investigation.
-			Type *memberType = memberExpr->member->get_type()->clone();
-			TypeSubstitution sub = objectType->genericSubstitution();
-			sub.apply( memberType );
-			if ( ! isPolyType( memberType, scopeTyVars ) ) {
-				// Not all members of a polymorphic type are themselves of polymorphic type; in this case the member expression should be wrapped and dereferenced to form an lvalue
-				CastExpr *ptrCastExpr = new CastExpr( newMemberExpr, new PointerType( Type::Qualifiers(), memberType->clone() ) );
-				UntypedExpr *derefExpr = UntypedExpr::createDeref( ptrCastExpr );
-				newMemberExpr = derefExpr;
-			}
-
-			delete memberType;
-			delete memberExpr;
-			return newMemberExpr;
-		}
-
-		void PolyGenericCalculator::premutate( AddressExpr * addrExpr ) {
-			GuardValue( addrMember );
-			// is the argument a MemberExpr before mutating?
-			addrMember = dynamic_cast< MemberExpr * >( addrExpr->arg );
-		}
-
-		Expression * PolyGenericCalculator::postmutate( AddressExpr * addrExpr ) {
-			if ( addrMember && addrMember != addrExpr->arg ) {
-				// arg was a MemberExpr and has been mutated
-				if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( addrExpr->arg ) ) {
-					if ( InitTweak::getFunctionName( untyped ) == "?+?" ) {
-						// MemberExpr was converted to pointer+offset, and it is not valid C to take the address of an addition, so strip the address-of
-						// TODO: should  addrExpr->arg->result be changed to addrExpr->result?
-						Expression * ret = addrExpr->arg;
-						addrExpr->arg = nullptr;
-						std::swap( addrExpr->env, ret->env );
-						delete addrExpr;
-						return ret;
-					}
-				}
-			}
-			return addrExpr;
-		}
-
-		ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) {
-			ObjectDecl *newObj = new ObjectDecl( name, Type::StorageClasses(), LinkageSpec::C, nullptr, type, init );
-			stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
-			return newObj;
-		}
-
-		void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
-			for ( Type * const param : otypeParams ) {
-				if ( findGeneric( param ) ) {
-					// push size/align vars for a generic parameter back
-					std::string paramName = mangleType( param );
-					layoutCall->get_args().push_back( new NameExpr( sizeofName( paramName ) ) );
-					layoutCall->get_args().push_back( new NameExpr( alignofName( paramName ) ) );
-				} else {
-					layoutCall->get_args().push_back( new SizeofExpr( param->clone() ) );
-					layoutCall->get_args().push_back( new AlignofExpr( param->clone() ) );
-				}
-			}
-		}
-
-		/// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
-		bool findGenericParams( std::list< TypeDecl* > const &baseParams, std::list< Expression* > const &typeParams, std::list< Type* > &out ) {
-			bool hasDynamicLayout = false;
-
-			for ( auto paramPair : group_iterate( baseParams, typeParams ) ) {
-				TypeDecl * baseParam = std::get<0>( paramPair );
-				Expression * typeParam = std::get<1>( paramPair );
-				// skip non-otype parameters
-				if ( ! baseParam->isComplete() ) continue;
-				TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( typeParam );
-				assert( typeExpr && "all otype parameters should be type expressions" );
-
-				Type *type = typeExpr->get_type();
-				out.push_back( type );
-				if ( isPolyType( type ) ) hasDynamicLayout = true;
-			}
-
-			return hasDynamicLayout;
-		}
-
-		bool PolyGenericCalculator::findGeneric( Type const *ty ) {
-			ty = replaceTypeInst( ty, env );
-
-			if ( auto typeInst = dynamic_cast< TypeInstType const * >( ty ) ) {
-				if ( scopeTyVars.contains( typeInst->get_name() ) ) {
-					// NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
-					return true;
-				}
-				return false;
-			} else if ( auto structTy = dynamic_cast< StructInstType const * >( ty ) ) {
-				// check if this type already has a layout generated for it
-				std::string typeName = mangleType( ty );
-				if ( knownLayouts.contains( typeName ) ) return true;
-
-				// check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
-				std::list< Type* > otypeParams;
-				if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->parameters, otypeParams ) ) return false;
-
-				// insert local variables for layout and generate call to layout function
-				knownLayouts.insert( typeName );  // done early so as not to interfere with the later addition of parameters to the layout call
-				Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-
-				int n_members = structTy->get_baseStruct()->get_members().size();
-				if ( n_members == 0 ) {
-					// all empty structs have the same layout - size 1, align 1
-					makeVar( sizeofName( typeName ), layoutType, new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) );
-					makeVar( alignofName( typeName ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) );
-					// NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
-				} else {
-					ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
-					ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
-					ObjectDecl *offsetVar = makeVar( offsetofName( typeName ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from_int( n_members ) ), false, false ) );
-
-					// generate call to layout function
-					UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( structTy->get_baseStruct() ) ) );
-					layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
-					layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
-					layoutCall->get_args().push_back( new VariableExpr( offsetVar ) );
-					addOtypeParamsToLayoutCall( layoutCall, otypeParams );
-
-					stmtsToAddBefore.push_back( new ExprStmt( layoutCall ) );
-				}
-
-				// std::cout << "TRUE 2" << std::endl;
-
-				return true;
-			} else if ( auto unionTy = dynamic_cast< UnionInstType const * >( ty ) ) {
-				// check if this type already has a layout generated for it
-				std::string typeName = mangleType( ty );
-				if ( knownLayouts.contains( typeName ) ) return true;
-
-				// check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
-				std::list< Type* > otypeParams;
-				if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->parameters, otypeParams ) ) return false;
-
-				// insert local variables for layout and generate call to layout function
-				knownLayouts.insert( typeName );  // done early so as not to interfere with the later addition of parameters to the layout call
-				Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-
-				ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
-				ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
-
-				// generate call to layout function
-				UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( unionTy->get_baseUnion() ) ) );
-				layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
-				layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
-				addOtypeParamsToLayoutCall( layoutCall, otypeParams );
-
-				stmtsToAddBefore.push_back( new ExprStmt( layoutCall ) );
-
-				return true;
-			}
-
-			return false;
-		}
-
-		Expression * PolyGenericCalculator::genSizeof( Type* ty ) {
-			if ( ArrayType * aty = dynamic_cast<ArrayType *>(ty) ) {
-				// generate calculated size for possibly generic array
-				Expression * sizeofBase = genSizeof( aty->get_base() );
-				if ( ! sizeofBase ) return nullptr;
-				Expression * dim = aty->get_dimension();
-				aty->set_dimension( nullptr );
-				return makeOp( "?*?", sizeofBase, dim );
-			} else if ( findGeneric( ty ) ) {
-				// generate calculated size for generic type
-				return new NameExpr( sizeofName( mangleType( ty ) ) );
-			} else return nullptr;
-		}
-
-		Expression *PolyGenericCalculator::postmutate( SizeofExpr *sizeofExpr ) {
-			Type *ty = sizeofExpr->get_isType() ?
-				sizeofExpr->get_type() : sizeofExpr->get_expr()->get_result();
-
-			Expression * gen = genSizeof( ty );
-			if ( gen ) {
-				delete sizeofExpr;
-				return gen;
-			} else return sizeofExpr;
-		}
-
-		Expression *PolyGenericCalculator::postmutate( AlignofExpr *alignofExpr ) {
-			Type *ty = alignofExpr->get_isType() ? alignofExpr->get_type() : alignofExpr->get_expr()->get_result();
-			if ( findGeneric( ty ) ) {
-				Expression *ret = new NameExpr( alignofName( mangleType( ty ) ) );
-				delete alignofExpr;
-				return ret;
-			}
-			return alignofExpr;
-		}
-
-		Expression *PolyGenericCalculator::postmutate( OffsetofExpr *offsetofExpr ) {
-			// only mutate expressions for polymorphic structs/unions
-			Type *ty = offsetofExpr->get_type();
-			if ( ! findGeneric( ty ) ) return offsetofExpr;
-
-			if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
-				// replace offsetof expression by index into offset array
-				long i = findMember( offsetofExpr->get_member(), structType->get_baseStruct()->get_members() );
-				if ( i == -1 ) return offsetofExpr;
-
-				Expression *offsetInd = makeOffsetIndex( ty, i );
-				delete offsetofExpr;
-				return offsetInd;
-			} else if ( dynamic_cast< UnionInstType* >( ty ) ) {
-				// all union members are at offset zero
-				delete offsetofExpr;
-				return new ConstantExpr( Constant::from_ulong( 0 ) );
-			} else return offsetofExpr;
-		}
-
-		Expression *PolyGenericCalculator::postmutate( OffsetPackExpr *offsetPackExpr ) {
-			StructInstType *ty = offsetPackExpr->get_type();
-
-			Expression *ret = 0;
-			if ( findGeneric( ty ) ) {
-				// pull offset back from generated type information
-				ret = new NameExpr( offsetofName( mangleType( ty ) ) );
-			} else {
-				std::string offsetName = offsetofName( mangleType( ty ) );
-				if ( knownOffsets.contains( offsetName ) ) {
-					// use the already-generated offsets for this type
-					ret = new NameExpr( offsetName );
-				} else {
-					knownOffsets.insert( offsetName );
-
-					std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
-					Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-
-					// build initializer list for offset array
-					std::list< Initializer* > inits;
-					for ( Declaration * const member : baseMembers ) {
-						DeclarationWithType *memberDecl = dynamic_cast< DeclarationWithType* >( member );
-						assertf( memberDecl, "Requesting offset of Non-DWT member: %s", toString( member ).c_str() );
-						inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
-					}
-
-					// build the offset array and replace the pack with a reference to it
-					ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from_ulong( baseMembers.size() ) ), false, false ),
-							new ListInit( inits ) );
-					ret = new VariableExpr( offsetArray );
-				}
-			}
-
-			delete offsetPackExpr;
-			return ret;
-		}
-
-		void PolyGenericCalculator::beginScope() {
-			knownLayouts.beginScope();
-			knownOffsets.beginScope();
-		}
-
-		void PolyGenericCalculator::endScope() {
-			knownLayouts.endScope();
-			knownOffsets.endScope();
-		}
-
-////////////////////////////////////////// Eraser ///////////////////////////////////////////////
-
-		void Eraser::premutate( ObjectDecl * objectDecl ) {
-			ScrubTyVars::scrubAll( objectDecl );
-		}
-
-		void Eraser::premutate( FunctionDecl * functionDecl ) {
-			ScrubTyVars::scrubAll( functionDecl );
-		}
-
-		void Eraser::premutate( TypedefDecl * typedefDecl ) {
-			ScrubTyVars::scrubAll( typedefDecl );
-		}
-
-		/// Strips the members from a generic aggregate
-		static void stripGenericMembers( AggregateDecl * decl ) {
-			if ( ! decl->parameters.empty() ) decl->members.clear();
-		}
-
-		void Eraser::premutate( StructDecl * structDecl ) {
-			stripGenericMembers( structDecl );
-		}
-
-		void Eraser::premutate( UnionDecl * unionDecl ) {
-			stripGenericMembers( unionDecl );
-		}
-	} // anonymous namespace
-} // namespace GenPoly
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/GenPoly/FindFunction.cc
===================================================================
--- src/GenPoly/FindFunction.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/GenPoly/FindFunction.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -20,75 +20,9 @@
 #include "AST/Pass.hpp"                 // for Pass
 #include "AST/Type.hpp"
-#include "Common/PassVisitor.h"         // for PassVisitor
 #include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::iterator
 #include "GenPoly/GenPoly.h"            // for TyVarMap
 #include "ScrubTyVars.h"                // for ScrubTyVars
-#include "SynTree/Declaration.h"        // for DeclarationWithType, TypeDecl
-#include "SynTree/Mutator.h"            // for Mutator, mutateAll
-#include "SynTree/Type.h"               // for FunctionType, Type, Type::For...
 
 namespace GenPoly {
-	class FindFunction : public WithGuards, public WithVisitorRef<FindFunction>, public WithShortCircuiting {
-	  public:
-		FindFunction( std::list< FunctionType const* > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate );
-
-		void premutate( FunctionType * functionType );
-		Type * postmutate( FunctionType * functionType );
-		void premutate( PointerType * pointerType );
-	  private:
-		void handleForall( const Type::ForallList &forall );
-
-		std::list< FunctionType const * > & functions;
-		TyVarMap tyVars;
-		bool replaceMode;
-		FindFunctionPredicate predicate;
-	};
-
-	void findFunction( Type *type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
-		PassVisitor<FindFunction> finder( functions, tyVars, false, predicate );
-		type->acceptMutator( finder );
-	}
-
-	void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
-		PassVisitor<FindFunction> finder( functions, tyVars, true, predicate );
-		type = type->acceptMutator( finder );
-	}
-
-	FindFunction::FindFunction( std::list< FunctionType const * > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate )
-		: functions( functions ), tyVars( tyVars ), replaceMode( replaceMode ), predicate( predicate ) {
-	}
-
-	void FindFunction::handleForall( const Type::ForallList &forall ) {
-		for ( const Declaration * td : forall ) {
-			TyVarMap::iterator var = tyVars.find( td->name );
-			if ( var != tyVars.end() ) {
-				tyVars.erase( var->first );
-			} // if
-		} // for
-	}
-
-	void FindFunction::premutate( FunctionType * functionType ) {
-		visit_children = false;
-		GuardScope( tyVars );
-		handleForall( functionType->get_forall() );
-		mutateAll( functionType->get_returnVals(), *visitor );
-	}
-
-	Type * FindFunction::postmutate( FunctionType * functionType ) {
-		Type *ret = functionType;
-		if ( predicate( functionType, tyVars ) ) {
-			functions.push_back( functionType );
-			if ( replaceMode ) {
-				// replace type parameters in function type with void*
-				ret = ScrubTyVars::scrub( functionType->clone(), tyVars );
-			} // if
-		} // if
-		return ret;
-	}
-
-	void FindFunction::premutate( PointerType * pointerType ) {
-		GuardScope( tyVars );
-		handleForall( pointerType->get_forall() );
-	}
 
 namespace {
@@ -154,5 +88,4 @@
 void FindFunctionCore::previsit( ast::PointerType const * /*type*/ ) {
 	GuardScope( typeVars );
-	//handleForall( type->forall );
 }
 
@@ -164,8 +97,4 @@
 	ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, false );
 	type->accept( pass );
-	//(void)type;
-	//(void)functions;
-	//(void)typeVars;
-	//(void)predicate;
 }
 
@@ -175,8 +104,4 @@
 	ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, true );
 	return type->accept( pass );
-	//(void)functions;
-	//(void)typeVars;
-	//(void)predicate;
-	//return type;
 }
 
Index: src/GenPoly/FindFunction.h
===================================================================
--- src/GenPoly/FindFunction.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/GenPoly/FindFunction.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,18 +16,7 @@
 #pragma once
 
-#include <list>       // for list
-
 #include "GenPoly.h"  // for TyVarMap
 
-class FunctionType;
-class Type;
-
 namespace GenPoly {
-	typedef bool (*FindFunctionPredicate)( FunctionType*, const TyVarMap& );
-
-	/// recursively walk `type`, placing all functions that match `predicate` under `tyVars` into `functions`
-	void findFunction( Type *type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
-	/// like `findFunction`, but also replaces the function type with void ()(void)
-	void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
 
 typedef bool (*FindFunctionPred)( const ast::FunctionType *, const TypeVarMap & );
Index: src/GenPoly/GenPoly.cc
===================================================================
--- src/GenPoly/GenPoly.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/GenPoly/GenPoly.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -29,8 +29,4 @@
 #include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
 #include "ResolvExpr/typeops.h"         // for flatten
-#include "SynTree/Constant.h"           // for Constant
-#include "SynTree/Expression.h"         // for Expression, TypeExpr, Constan...
-#include "SynTree/Type.h"               // for Type, StructInstType, UnionIn...
-#include "SynTree/TypeSubstitution.h"   // for TypeSubstitution
 
 using namespace std;
@@ -39,13 +35,4 @@
 	namespace {
 		/// Checks a parameter list for polymorphic parameters; will substitute according to env if present
-		bool hasPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {
-			for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
-				TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
-				assertf(paramType, "Aggregate parameters should be type expressions");
-				if ( isPolyType( paramType->get_type(), env ) ) return true;
-			}
-			return false;
-		}
-
 		bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const ast::TypeSubstitution * env ) {
 			for ( auto &param : params ) {
@@ -58,13 +45,4 @@
 
 		/// Checks a parameter list for polymorphic parameters from tyVars; will substitute according to env if present
-		bool hasPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
-			for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
-				TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
-				assertf(paramType, "Aggregate parameters should be type expressions");
-				if ( isPolyType( paramType->get_type(), tyVars, env ) ) return true;
-			}
-			return false;
-		}
-
 		bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const TypeVarMap & typeVars, const ast::TypeSubstitution * env ) {
 			for ( auto & param : params ) {
@@ -77,13 +55,4 @@
 
 		/// Checks a parameter list for dynamic-layout parameters from tyVars; will substitute according to env if present
-		bool hasDynParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
-			for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
-				TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
-				assertf(paramType, "Aggregate parameters should be type expressions");
-				if ( isDynType( paramType->get_type(), tyVars, env ) ) return true;
-			}
-			return false;
-		}
-
 		bool hasDynParams(
 				const std::vector<ast::ptr<ast::Expr>> & params,
@@ -99,42 +68,4 @@
 			return false;
 		}
-
-		/// Checks a parameter list for inclusion of polymorphic parameters; will substitute according to env if present
-		bool includesPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {
-			for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
-				TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
-				assertf(paramType, "Aggregate parameters should be type expressions");
-				if ( includesPolyType( paramType->get_type(), env ) ) return true;
-			}
-			return false;
-		}
-
-		/// Checks a parameter list for inclusion of polymorphic parameters from tyVars; will substitute according to env if present
-		bool includesPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
-			for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
-				TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
-				assertf(paramType, "Aggregate parameters should be type expressions");
-				if ( includesPolyType( paramType->get_type(), tyVars, env ) ) return true;
-			}
-			return false;
-		}
-	}
-
-	Type* replaceTypeInst( Type* type, const TypeSubstitution* env ) {
-		if ( ! env ) return type;
-		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
-			Type *newType = env->lookup( typeInst->get_name() );
-			if ( newType ) return newType;
-		}
-		return type;
-	}
-
-	const Type* replaceTypeInst( const Type* type, const TypeSubstitution* env ) {
-		if ( ! env ) return type;
-		if ( auto typeInst = dynamic_cast< const TypeInstType* >( type ) ) {
-			Type *newType = env->lookup( typeInst->get_name() );
-			if ( newType ) return newType;
-		}
-		return type;
 	}
 
@@ -146,19 +77,4 @@
 		}
 		return type;
-	}
-
-	Type *isPolyType( Type *type, const TypeSubstitution *env ) {
-		type = replaceTypeInst( type, env );
-
-		if ( dynamic_cast< TypeInstType * >( type ) ) {
-			return type;
-		} else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
-			return isPolyType( arrayType->base, env );
-		} else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
-			if ( hasPolyParams( structType->get_parameters(), env ) ) return type;
-		} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
-			if ( hasPolyParams( unionType->get_parameters(), env ) ) return type;
-		}
-		return 0;
 	}
 
@@ -178,21 +94,4 @@
 	}
 
-	Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
-		type = replaceTypeInst( type, env );
-
-		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
-			if ( tyVars.contains( typeInst->get_name() ) ) {
-				return type;
-			}
-		} else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
-			return isPolyType( arrayType->base, tyVars, env );
-		} else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
-			if ( hasPolyParams( structType->get_parameters(), tyVars, env ) ) return type;
-		} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
-			if ( hasPolyParams( unionType->get_parameters(), tyVars, env ) ) return type;
-		}
-		return 0;
-	}
-
 const ast::Type * isPolyType( const ast::Type * type,
 		const TypeVarMap & typeVars, const ast::TypeSubstitution * subst ) {
@@ -211,20 +110,4 @@
 }
 
-	ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
-		type = replaceTypeInst( type, env );
-
-		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
-			auto var = tyVars.find( typeInst->get_name() );
-			if ( var != tyVars.end() && var->second.isComplete ) {
-				return typeInst;
-			}
-		} else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
-			if ( hasDynParams( structType->get_parameters(), tyVars, env ) ) return structType;
-		} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
-			if ( hasDynParams( unionType->get_parameters(), tyVars, env ) ) return unionType;
-		}
-		return 0;
-	}
-
 const ast::BaseInstType * isDynType(
 		const ast::Type * type, const TypeVarMap & typeVars,
@@ -249,10 +132,4 @@
 }
 
-	ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &forallTypes ) {
-		if ( function->get_returnVals().empty() ) return 0;
-
-		return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
-	}
-
 const ast::BaseInstType *isDynRet(
 		const ast::FunctionType * type, const TypeVarMap & typeVars ) {
@@ -262,12 +139,4 @@
 }
 
-	ReferenceToType *isDynRet( FunctionType *function ) {
-		if ( function->get_returnVals().empty() ) return 0;
-
-		TyVarMap forallTypes( TypeDecl::Data{} );
-		makeTyVarMap( function, forallTypes );
-		return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
-	}
-
 const ast::BaseInstType *isDynRet( const ast::FunctionType * func ) {
 	if ( func->returns.empty() ) return nullptr;
@@ -278,19 +147,4 @@
 }
 
-	bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) {
-// 		if ( ! adaptee->get_returnVals().empty() && isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
-// 			return true;
-// 		} // if
-		if ( isDynRet( adaptee, tyVars ) ) return true;
-
-		for ( std::list< DeclarationWithType* >::const_iterator innerArg = adaptee->get_parameters().begin(); innerArg != adaptee->get_parameters().end(); ++innerArg ) {
-// 			if ( isPolyType( (*innerArg)->get_type(), tyVars ) ) {
-			if ( isDynType( (*innerArg)->get_type(), tyVars ) ) {
-				return true;
-			} // if
-		} // for
-		return false;
-	}
-
 bool needsAdapter(
 		ast::FunctionType const * adaptee, const TypeVarMap & typeVars ) {
@@ -304,22 +158,4 @@
 	return false;
 }
-
-	Type *isPolyPtr( Type *type, const TypeSubstitution *env ) {
-		type = replaceTypeInst( type, env );
-
-		if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
-			return isPolyType( ptr->get_base(), env );
-		}
-		return 0;
-	}
-
-	Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
-		type = replaceTypeInst( type, env );
-
-		if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
-			return isPolyType( ptr->get_base(), tyVars, env );
-		}
-		return 0;
-	}
 
 const ast::Type * isPolyPtr(
@@ -333,38 +169,4 @@
 	return nullptr;
 }
-
-	Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) {
-		int dummy;
-		if ( ! levels ) { levels = &dummy; }
-		*levels = 0;
-
-		while ( true ) {
-			type = replaceTypeInst( type, env );
-
-			if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
-				type = ptr->get_base();
-				++(*levels);
-			} else break;
-		}
-
-		return isPolyType( type, env );
-	}
-
-	Type * hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels, const TypeSubstitution *env ) {
-		int dummy;
-		if ( ! levels ) { levels = &dummy; }
-		*levels = 0;
-
-		while ( true ) {
-			type = replaceTypeInst( type, env );
-
-			if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
-				type = ptr->get_base();
-				++(*levels);
-			} else break;
-		}
-
-		return isPolyType( type, tyVars, env );
-	}
 
 ast::Type const * hasPolyBase(
@@ -388,45 +190,4 @@
 }
 
-	bool includesPolyType( Type *type, const TypeSubstitution *env ) {
-		type = replaceTypeInst( type, env );
-
-		if ( dynamic_cast< TypeInstType * >( type ) ) {
-			return true;
-		} else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) {
-			if ( includesPolyType( pointerType->get_base(), env ) ) return true;
-		} else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
-			if ( includesPolyParams( structType->get_parameters(), env ) ) return true;
-		} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
-			if ( includesPolyParams( unionType->get_parameters(), env ) ) return true;
-		}
-		return false;
-	}
-
-	bool includesPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
-		type = replaceTypeInst( type, env );
-
-		if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) {
-			if ( tyVars.contains( typeInstType->get_name() ) ) {
-				return true;
-			}
-		} else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) {
-			if ( includesPolyType( pointerType->get_base(), tyVars, env ) ) return true;
-		} else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
-			if ( includesPolyParams( structType->get_parameters(), tyVars, env ) ) return true;
-		} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
-			if ( includesPolyParams( unionType->get_parameters(), tyVars, env ) ) return true;
-		}
-		return false;
-	}
-
-	FunctionType * getFunctionType( Type *ty ) {
-		PointerType *ptrType;
-		if ( ( ptrType = dynamic_cast< PointerType* >( ty ) ) ) {
-			return dynamic_cast< FunctionType* >( ptrType->get_base() ); // pointer if FunctionType, NULL otherwise
-		} else {
-			return dynamic_cast< FunctionType* >( ty ); // pointer if FunctionType, NULL otherwise
-		}
-	}
-
 	const ast::FunctionType * getFunctionType( const ast::Type * ty ) {
 		if ( auto pty = dynamic_cast< const ast::PointerType * >( ty ) ) {
@@ -437,43 +198,4 @@
 	}
 
-	VariableExpr * getBaseVar( Expression *expr, int *levels ) {
-		int dummy;
-		if ( ! levels ) { levels = &dummy; }
-		*levels = 0;
-
-		while ( true ) {
-			if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( expr ) ) {
-				return varExpr;
-			} else if ( MemberExpr *memberExpr = dynamic_cast< MemberExpr* >( expr ) ) {
-				expr = memberExpr->get_aggregate();
-			} else if ( AddressExpr *addressExpr = dynamic_cast< AddressExpr* >( expr ) ) {
-				expr = addressExpr->get_arg();
-			} else if ( UntypedExpr *untypedExpr = dynamic_cast< UntypedExpr* >( expr ) ) {
-				// look for compiler-inserted dereference operator
-				NameExpr *fn = dynamic_cast< NameExpr* >( untypedExpr->get_function() );
-				if ( ! fn || fn->get_name() != std::string("*?") ) return 0;
-				expr = *untypedExpr->begin_args();
-			} else if ( CommaExpr *commaExpr = dynamic_cast< CommaExpr* >( expr ) ) {
-				// copy constructors insert comma exprs, look at second argument which contains the variable
-				expr = commaExpr->get_arg2();
-				continue;
-			} else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( expr ) ) {
-				int lvl1;
-				int lvl2;
-				VariableExpr * var1 = getBaseVar( condExpr->get_arg2(), &lvl1 );
-				VariableExpr * var2 = getBaseVar( condExpr->get_arg3(), &lvl2 );
-				if ( lvl1 == lvl2 && var1 && var2 && var1->get_var() == var2->get_var() ) {
-					*levels = lvl1;
-					return var1;
-				}
-				break;
-			} else break;
-
-			++(*levels);
-		}
-
-		return 0;
-	}
-
 	namespace {
 		/// Checks if is a pointer to D
@@ -488,20 +210,4 @@
 		inline D const * as( B const * p ) {
 			return reinterpret_cast<D const *>( p );
-		}
-
-		/// Flattens a declaration list
-		template<typename Output>
-		void flattenList( list< DeclarationWithType* > src, Output out ) {
-			for ( DeclarationWithType* decl : src ) {
-				ResolvExpr::flatten( decl->get_type(), out );
-			}
-		}
-
-		/// Flattens a list of types
-		template<typename Output>
-		void flattenList( list< Type* > src, Output out ) {
-			for ( Type* ty : src ) {
-				ResolvExpr::flatten( ty, out );
-			}
 		}
 
@@ -515,24 +221,4 @@
 		}
 
-		/// Checks if two lists of parameters are equal up to polymorphic substitution.
-		bool paramListsPolyCompatible( const list< Expression* >& aparams, const list< Expression* >& bparams ) {
-			if ( aparams.size() != bparams.size() ) return false;
-
-			for ( list< Expression* >::const_iterator at = aparams.begin(), bt = bparams.begin();
-					at != aparams.end(); ++at, ++bt ) {
-				TypeExpr *aparam = dynamic_cast< TypeExpr* >(*at);
-				assertf(aparam, "Aggregate parameters should be type expressions");
-				TypeExpr *bparam = dynamic_cast< TypeExpr* >(*bt);
-				assertf(bparam, "Aggregate parameters should be type expressions");
-
-				// xxx - might need to let VoidType be a wildcard here too; could have some voids
-				// stuffed in for dtype-statics.
-				// if ( is<VoidType>( aparam->get_type() ) || is<VoidType>( bparam->get_type() ) ) continue;
-				if ( ! typesPolyCompatible( aparam->get_type(), bparam->get_type() ) ) return false;
-			}
-
-			return true;
-		}
-
 		bool paramListsPolyCompatible(
 				std::vector<ast::ptr<ast::Expr>> const & lparams,
@@ -559,94 +245,4 @@
 			return true;
 		}
-	}
-
-	bool typesPolyCompatible( Type *a, Type *b ) {
-		type_index aid{ typeid(*a) };
-		// polymorphic types always match
-		if ( aid == type_index{typeid(TypeInstType)} ) return true;
-
-		type_index bid{ typeid(*b) };
-		// polymorphic types always match
-		if ( bid == type_index{typeid(TypeInstType)} ) return true;
-
-		// can't match otherwise if different types
-		if ( aid != bid ) return false;
-
-		// recurse through type structure (conditions borrowed from Unify.cc)
-		if ( aid == type_index{typeid(BasicType)} ) {
-			return as<BasicType>(a)->get_kind() == as<BasicType>(b)->get_kind();
-		} else if ( aid == type_index{typeid(PointerType)} ) {
-			PointerType *ap = as<PointerType>(a), *bp = as<PointerType>(b);
-
-			// void pointers should match any other pointer type
-			return is<VoidType>( ap->get_base() ) || is<VoidType>( bp->get_base() )
-				|| typesPolyCompatible( ap->get_base(), bp->get_base() );
-		} else if ( aid == type_index{typeid(ReferenceType)} ) {
-			ReferenceType *ap = as<ReferenceType>(a), *bp = as<ReferenceType>(b);
-			return is<VoidType>( ap->get_base() ) || is<VoidType>( bp->get_base() )
-				|| typesPolyCompatible( ap->get_base(), bp->get_base() );
-		} else if ( aid == type_index{typeid(ArrayType)} ) {
-			ArrayType *aa = as<ArrayType>(a), *ba = as<ArrayType>(b);
-
-			if ( aa->get_isVarLen() ) {
-				if ( ! ba->get_isVarLen() ) return false;
-			} else {
-				if ( ba->get_isVarLen() ) return false;
-
-				ConstantExpr *ad = dynamic_cast<ConstantExpr*>( aa->get_dimension() );
-				ConstantExpr *bd = dynamic_cast<ConstantExpr*>( ba->get_dimension() );
-				if ( ad && bd
-						&& ad->get_constant()->get_value() != bd->get_constant()->get_value() )
-					return false;
-			}
-
-			return typesPolyCompatible( aa->get_base(), ba->get_base() );
-		} else if ( aid == type_index{typeid(FunctionType)} ) {
-			FunctionType *af = as<FunctionType>(a), *bf = as<FunctionType>(b);
-
-			vector<Type*> aparams, bparams;
-			flattenList( af->get_parameters(), back_inserter( aparams ) );
-			flattenList( bf->get_parameters(), back_inserter( bparams ) );
-			if ( aparams.size() != bparams.size() ) return false;
-
-			vector<Type*> areturns, breturns;
-			flattenList( af->get_returnVals(), back_inserter( areturns ) );
-			flattenList( bf->get_returnVals(), back_inserter( breturns ) );
-			if ( areturns.size() != breturns.size() ) return false;
-
-			for ( unsigned i = 0; i < aparams.size(); ++i ) {
-				if ( ! typesPolyCompatible( aparams[i], bparams[i] ) ) return false;
-			}
-			for ( unsigned i = 0; i < areturns.size(); ++i ) {
-				if ( ! typesPolyCompatible( areturns[i], breturns[i] ) ) return false;
-			}
-			return true;
-		} else if ( aid == type_index{typeid(StructInstType)} ) {
-			StructInstType *aa = as<StructInstType>(a), *ba = as<StructInstType>(b);
-
-			if ( aa->get_name() != ba->get_name() ) return false;
-			return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() );
-		} else if ( aid == type_index{typeid(UnionInstType)} ) {
-			UnionInstType *aa = as<UnionInstType>(a), *ba = as<UnionInstType>(b);
-
-			if ( aa->get_name() != ba->get_name() ) return false;
-			return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() );
-		} else if ( aid == type_index{typeid(EnumInstType)} ) {
-			return as<EnumInstType>(a)->get_name() == as<EnumInstType>(b)->get_name();
-		} else if ( aid == type_index{typeid(TraitInstType)} ) {
-			return as<TraitInstType>(a)->get_name() == as<TraitInstType>(b)->get_name();
-		} else if ( aid == type_index{typeid(TupleType)} ) {
-			TupleType *at = as<TupleType>(a), *bt = as<TupleType>(b);
-
-			vector<Type*> atypes, btypes;
-			flattenList( at->get_types(), back_inserter( atypes ) );
-			flattenList( bt->get_types(), back_inserter( btypes ) );
-			if ( atypes.size() != btypes.size() ) return false;
-
-			for ( unsigned i = 0; i < atypes.size(); ++i ) {
-				if ( ! typesPolyCompatible( atypes[i], btypes[i] ) ) return false;
-			}
-			return true;
-		} else return true; // VoidType, VarArgsType, ZeroType & OneType just need the same type
 	}
 
@@ -763,14 +359,4 @@
 }
 
-	bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) {
-		// is parameter is not polymorphic, don't need to box
-		if ( ! isPolyType( param, exprTyVars ) ) return false;
-		Type * newType = arg->clone();
-		if ( env ) env->apply( newType );
-		std::unique_ptr<Type> manager( newType );
-		// if the argument's type is polymorphic, we don't need to box again!
-		return ! isPolyType( newType );
-	}
-
 bool needsBoxing( const ast::Type * param, const ast::Type * arg,
 		const TypeVarMap & typeVars, const ast::TypeSubstitution * subst ) {
@@ -786,12 +372,4 @@
 	return !isPolyType( newType );
 }
-
-	bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) {
-		FunctionType * function = getFunctionType( appExpr->function->result );
-		assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
-		TyVarMap exprTyVars( TypeDecl::Data{} );
-		makeTyVarMap( function, exprTyVars );
-		return needsBoxing( param, arg, exprTyVars, env );
-	}
 
 bool needsBoxing(
@@ -806,8 +384,4 @@
 }
 
-	void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
-		tyVarMap.insert( tyVar->name, TypeDecl::Data{ tyVar } );
-	}
-
 void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) {
 	typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) );
@@ -817,14 +391,4 @@
 	typeVars.insert( ast::TypeEnvKey( *type ), ast::TypeData( type->base ) );
 }
-
-	void makeTyVarMap( Type *type, TyVarMap &tyVarMap ) {
-		for ( Type::ForallList::const_iterator tyVar = type->get_forall().begin(); tyVar != type->get_forall().end(); ++tyVar ) {
-			assert( *tyVar );
-			addToTyVarMap( *tyVar, tyVarMap );
-		}
-		if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) {
-			makeTyVarMap( pointer->get_base(), tyVarMap );
-		}
-	}
 
 void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars ) {
@@ -846,11 +410,4 @@
 }
 
-	void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {
-		for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {
-			os << i->first << " (" << i->second << ") ";
-		} // for
-		os << std::endl;
-	}
-
 } // namespace GenPoly
 
Index: src/GenPoly/GenPoly.h
===================================================================
--- src/GenPoly/GenPoly.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/GenPoly/GenPoly.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -23,6 +23,4 @@
 #include "AST/Fwd.hpp"            // for ApplicationExpr, BaseInstType, Func...
 #include "SymTab/Mangler.h"       // for Mangler
-#include "SynTree/Declaration.h"  // for TypeDecl::Data, AggregateDecl, Type...
-#include "SynTree/SynTree.h"      // for Visitor Nodes
 
 namespace ast {
@@ -32,5 +30,4 @@
 namespace GenPoly {
 
-	typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;
 	struct TypeVarMap : public ErasableScopedMap<ast::TypeEnvKey, ast::TypeData> {
 		TypeVarMap() : ErasableScopedMap( ast::TypeData() ) {}
@@ -38,91 +35,50 @@
 
 	/// Replaces a TypeInstType by its referrent in the environment, if applicable
-	Type* replaceTypeInst( Type* type, const TypeSubstitution* env );
-	const Type* replaceTypeInst( const Type* type, const TypeSubstitution* env );
 	const ast::Type * replaceTypeInst( const ast::Type *, const ast::TypeSubstitution * );
 
 	/// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided
-	Type *isPolyType( Type *type, const TypeSubstitution *env = 0 );
 	const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env = nullptr);
 
 	/// returns polymorphic type if is polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided
-	Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
 	const ast::Type * isPolyType( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst = nullptr );
 
 	/// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided
-	ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
 	const ast::BaseInstType *isDynType( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst = 0 );
 
 	/// true iff function has dynamic-layout return type under the given type variable map
-	ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &tyVars );
 	const ast::BaseInstType *isDynRet( const ast::FunctionType * type, const TypeVarMap & typeVars );
 
 	/// true iff function has dynamic-layout return type under the type variable map generated from its forall-parameters
-	ReferenceToType *isDynRet( FunctionType *function );
 	const ast::BaseInstType *isDynRet( const ast::FunctionType * func );
 
 	/// A function needs an adapter if it returns a dynamic-layout value or if any of its parameters have dynamic-layout type
-	bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVarr );
 	bool needsAdapter( ast::FunctionType const * adaptee, const TypeVarMap & typeVars );
 
-	/// returns polymorphic type if is pointer to polymorphic type, NULL otherwise; will look up substitution in env if provided
-	Type *isPolyPtr( Type *type, const TypeSubstitution *env = 0 );
-
 	/// returns polymorphic type if is pointer to polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided
-	Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
 	const ast::Type * isPolyPtr( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * env = 0 );
-
-	/// if the base type (after dereferencing N >= 0 pointers) is a polymorphic type, returns the base type, NULL otherwise;
-	/// N will be stored in levels, if provided, will look up substitution in env if provided
-	Type *hasPolyBase( Type *type, int *levels = 0, const TypeSubstitution *env = 0 );
 
 	/// if the base type (after dereferencing N >= 0 pointers) is a polymorphic type in tyVars, returns the base type, NULL otherwise;
 	/// N will be stored in levels, if provided, will look up substitution in env if provided
-	Type *hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels = 0, const TypeSubstitution *env = 0 );
 	const ast::Type * hasPolyBase( const ast::Type * type, const TypeVarMap & typeVars, int * levels = 0, const ast::TypeSubstitution * env = 0 );
 
-	/// true iff this type or some base of this type after dereferencing pointers is either polymorphic or a generic type with at least one
-	/// polymorphic parameter; will look up substitution in env if provided.
-	bool includesPolyType( Type *type, const TypeSubstitution *env = 0 );
-
-	/// true iff this type or some base of this type after dereferencing pointers is either polymorphic in tyVars, or a generic type with
-	/// at least one polymorphic parameter in tyVars; will look up substitution in env if provided.
-	bool includesPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
-
 	/// Returns a pointer to the base FunctionType if ty is the type of a function (or pointer to one), NULL otherwise
-	FunctionType *getFunctionType( Type *ty );
 	const ast::FunctionType * getFunctionType( const ast::Type * ty );
 
-	/// If expr (after dereferencing N >= 0 pointers) is a variable expression, returns the variable expression, NULL otherwise;
-	/// N will be stored in levels, if provided
-	VariableExpr *getBaseVar( Expression *expr, int *levels = 0 );
-
 	/// true iff types are structurally identical, where TypeInstType's match any type.
-	bool typesPolyCompatible( Type *aty, Type *bty );
 	bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs );
 
 	/// true if arg requires boxing given exprTyVars
-	bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env );
 	bool needsBoxing( const ast::Type * param, const ast::Type * arg, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst );
 
 	/// true if arg requires boxing in the call to appExpr
-	bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env );
 	bool needsBoxing( const ast::Type * param, const ast::Type * arg, const ast::ApplicationExpr * expr, const ast::TypeSubstitution * subst );
 
 	/// Adds the type variable `tyVar` to `tyVarMap`
-	void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap );
 	void addToTypeVarMap( const ast::TypeDecl * type, TypeVarMap & typeVars );
 	void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars );
 
 	/// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap`
-	void makeTyVarMap( Type *type, TyVarMap &tyVarMap );
 	void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars );
 	void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars );
-
-	/// Prints type variable map
-	void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap );
-
-	/// Gets the mangled name of this type; alias for SymTab::Mangler::mangleType().
-	inline std::string mangleType( const Type *ty ) { return SymTab::Mangler::mangleType( ty ); }
 
 	/// Gets the name of the sizeof parameter for the type, given its mangled name
@@ -136,5 +92,4 @@
 
 	/// Gets the name of the layout function for a given aggregate type, given its declaration
-	inline std::string layoutofName( AggregateDecl *decl ) { return std::string( "_layoutof_" ) + decl->get_name(); }
 	inline std::string layoutofName( ast::AggregateDecl const * decl ) {
 		return std::string( "_layoutof_" ) + decl->name;
Index: c/GenPoly/InstantiateGeneric.cc
===================================================================
--- src/GenPoly/InstantiateGeneric.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,591 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// InstantiateGeneric.cc --
-//
-// Author           : Aaron B. Moss
-// Created On       : Thu Aug 04 18:33:00 2016
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed Jul 16 10:17:00 2020
-// Update Count     : 2
-//
-#include "InstantiateGeneric.h"
-
-#include <cassert>                     // for assertf, assert
-#include <iterator>                    // for back_inserter, inserter
-#include <list>                        // for list, _List_const_iterator
-#include <utility>                     // for move, pair
-#include <vector>                      // for vector
-
-#include "CodeGen/OperatorTable.h"
-#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
-#include "Common/ScopedMap.h"          // for ScopedMap
-#include "Common/UniqueName.h"         // for UniqueName
-#include "Common/utility.h"            // for deleteAll, cloneAll
-#include "GenPoly.h"                   // for isPolyType, typesPolyCompatible
-#include "InitTweak/InitTweak.h"
-#include "ResolvExpr/AdjustExprType.hpp"  // for adjustExprType
-#include "ResolvExpr/Unify.h"          // for typesCompatible
-#include "ScopedSet.h"                 // for ScopedSet, ScopedSet<>::iterator
-#include "ScrubTyVars.h"               // for ScrubTyVars
-#include "SynTree/Declaration.h"       // for StructDecl, UnionDecl, TypeDecl
-#include "SynTree/Expression.h"        // for TypeExpr, Expression
-#include "SynTree/Mutator.h"           // for mutateAll
-#include "SynTree/Type.h"              // for StructInstType, UnionInstType
-#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
-#include "SynTree/Visitor.h"           // for acceptAll
-
-
-namespace GenPoly {
-
-	/// Abstracts type equality for a list of parameter types
-	struct TypeList {
-		TypeList() : params() {}
-		TypeList( const std::list< Type* > &_params ) : params() { cloneAll(_params, params); }
-		TypeList( std::list< Type* > &&_params ) : params( _params ) {}
-
-		TypeList( const TypeList &that ) : params() { cloneAll(that.params, params); }
-		TypeList( TypeList &&that ) : params( std::move( that.params ) ) {}
-
-		/// Extracts types from a list of TypeExpr*
-		TypeList( const std::list< TypeExpr* >& _params ) : params() {
-			for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) {
-				params.push_back( (*param)->get_type()->clone() );
-			}
-		}
-
-		TypeList& operator= ( const TypeList &that ) {
-			deleteAll( params );
-
-			params.clear();
-			cloneAll( that.params, params );
-
-			return *this;
-		}
-
-		TypeList& operator= ( TypeList &&that ) {
-			deleteAll( params );
-
-			params = std::move( that.params );
-
-			return *this;
-		}
-
-		~TypeList() { deleteAll( params ); }
-
-		bool operator== ( const TypeList& that ) const {
-			if ( params.size() != that.params.size() ) return false;
-
-			for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {
-				if ( ! typesPolyCompatible( *it, *jt ) ) return false;
-			}
-			return true;
-		}
-
-		std::list< Type* > params;  ///< Instantiation parameters
-	};
-
-	/// Maps a key and a TypeList to the some value, accounting for scope
-	template< typename Key, typename Value >
-	class InstantiationMap {
-		/// Wraps value for a specific (Key, TypeList) combination
-		typedef std::pair< TypeList, Value* > Instantiation;
-		/// List of TypeLists paired with their appropriate values
-		typedef std::vector< Instantiation > ValueList;
-		/// Underlying map type; maps keys to a linear list of corresponding TypeLists and values
-		typedef ScopedMap< Key*, ValueList > InnerMap;
-
-		InnerMap instantiations;  ///< instantiations
-
-	public:
-		/// Starts a new scope
-		void beginScope() { instantiations.beginScope(); }
-
-		/// Ends a scope
-		void endScope() { instantiations.endScope(); }
-
-		/// Gets the value for the (key, typeList) pair, returns NULL on none such.
-		Value *lookup( Key *key, const std::list< TypeExpr* >& params ) const {
-			TypeList typeList( params );
-
-			// scan scopes for matches to the key
-			for ( typename InnerMap::const_iterator insts = instantiations.find( key ); insts != instantiations.end(); insts = instantiations.findNext( insts, key ) ) {
-				for ( typename ValueList::const_reverse_iterator inst = insts->second.rbegin(); inst != insts->second.rend(); ++inst ) {
-					if ( inst->first == typeList ) return inst->second;
-				}
-			}
-			// no matching instantiations found
-			return 0;
-		}
-
-		/// Adds a value for a (key, typeList) pair to the current scope
-		void insert( Key *key, const std::list< TypeExpr* > &params, Value *value ) {
-			auto it = instantiations.findAt( instantiations.currentScope(), key );
-			if ( it == instantiations.end() ) {
-				instantiations.insert( key, ValueList{ Instantiation{ TypeList( params ), value } } );
-			} else {
-				it->second.push_back( Instantiation{ TypeList( params ), value } );
-			}
-		}
-	};
-
-	/// Possible options for a given specialization of a generic type
-	enum class genericType {
-		dtypeStatic,  ///< Concrete instantiation based solely on {d,f}type-to-void conversions
-		concrete,     ///< Concrete instantiation requiring at least one parameter type
-		dynamic       ///< No concrete instantiation
-	};
-
-	genericType& operator |= ( genericType& gt, const genericType& ht ) {
-		switch ( gt ) {
-		case genericType::dtypeStatic:
-			gt = ht;
-			break;
-		case genericType::concrete:
-			if ( ht == genericType::dynamic ) { gt = genericType::dynamic; }
-			break;
-		case genericType::dynamic:
-			// nothing possible
-			break;
-		}
-		return gt;
-	}
-
-	/// Add cast to dtype-static member expressions so that type information is not lost in GenericInstantiator
-	struct FixDtypeStatic final : public WithGuards, public WithVisitorRef<FixDtypeStatic>, public WithShortCircuiting, public WithStmtsToAdd {
-		Expression * postmutate( MemberExpr * memberExpr );
-
-		void premutate( ApplicationExpr * appExpr );
-		void premutate( AddressExpr * addrExpr );
-
-		template<typename AggrInst>
-		Expression * fixMemberExpr( AggrInst * inst, MemberExpr * memberExpr );
-
-		bool isLvalueArg = false;
-	};
-
-	/// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
-	struct GenericInstantiator final : public WithConstTypeSubstitution, public WithDeclsToAdd, public WithVisitorRef<GenericInstantiator>, public WithGuards {
-		/// Map of (generic type, parameter list) pairs to concrete type instantiations
-		InstantiationMap< AggregateDecl, AggregateDecl > instantiations;
-		/// Set of types which are dtype-only generic (and therefore have static layout)
-		std::set<AggregateDecl *> dtypeStatics;
-		/// Namer for concrete types
-		UniqueName typeNamer;
-		/// Should not make use of type environment to replace types of function parameter and return values.
-		bool inFunctionType = false;
-		/// Index of current member, used to recreate MemberExprs with the member from an instantiation
-		int memberIndex = -1;
-		GenericInstantiator() : instantiations(), dtypeStatics(), typeNamer("_conc_") {}
-
-		Type* postmutate( StructInstType *inst );
-		Type* postmutate( UnionInstType *inst );
-
-		// fix MemberExprs to use the member from the instantiation
-		void premutate( MemberExpr * memberExpr );
-		Expression * postmutate( MemberExpr * memberExpr );
-
-		void premutate( FunctionType * ) {
-			GuardValue( inFunctionType );
-			inFunctionType = true;
-		}
-
-		void beginScope();
-		void endScope();
-	private:
-		/// Wrap instantiation lookup for structs
-		StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)instantiations.lookup( inst->get_baseStruct(), typeSubs ); }
-		/// Wrap instantiation lookup for unions
-		UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)instantiations.lookup( inst->get_baseUnion(), typeSubs ); }
-		/// Wrap instantiation insertion for structs
-		void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { instantiations.insert( inst->get_baseStruct(), typeSubs, decl ); }
-		/// Wrap instantiation insertion for unions
-		void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); }
-
-		void replaceParametersWithConcrete( std::list< Expression* >& params );
-		Type *replaceWithConcrete( Type *type, bool doClone );
-
-		/// Strips a dtype-static aggregate decl of its type parameters, marks it as stripped
-		void stripDtypeParams( AggregateDecl *base, std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs );
-	};
-
-	void instantiateGeneric( std::list< Declaration* > &translationUnit ) {
-		PassVisitor<FixDtypeStatic> fixer;
-		PassVisitor<GenericInstantiator> instantiator;
-
-		mutateAll( translationUnit, fixer );
-		mutateAll( translationUnit, instantiator );
-	}
-
-	bool isDtypeStatic( const std::list< TypeDecl* >& baseParams ) {
-		return std::all_of( baseParams.begin(), baseParams.end(), []( TypeDecl * td ) { return ! td->isComplete(); } );
-	}
-
-	/// Makes substitutions of params into baseParams; returns dtypeStatic if there is a concrete instantiation based only on {d,f}type-to-void conversions,
-	/// concrete if there is a concrete instantiation requiring at least one parameter type, and dynamic if there is no concrete instantiation
-	genericType makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {
-		genericType gt = genericType::dtypeStatic;
-
-		// substitute concrete types for given parameters, and incomplete types for placeholders
-		std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
-		std::list< Expression* >::const_iterator param = params.begin();
-		for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) {
-			TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
-			assert(paramType && "Aggregate parameters should be type expressions");
-
-			if ( (*baseParam)->isComplete() ) {
-				// substitute parameter for complete (otype or sized dtype) type
-				if ( isPolyType( paramType->get_type() ) ) {
-					// substitute polymorphic parameter type in to generic type
-					out.push_back( paramType->clone() );
-					gt = genericType::dynamic;
-				} else {
-					// normalize possibly dtype-static parameter type
-					out.push_back( new TypeExpr{
-						ScrubTyVars::scrubAll( paramType->get_type()->clone() ) } );
-					gt |= genericType::concrete;
-				}
-			} else switch ( (*baseParam)->get_kind() ) {
-				case TypeDecl::Dtype:
-					// can pretend that any incomplete dtype is `void`
-					out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
-					break;
-				case TypeDecl::Ftype:
-					// can pretend that any ftype is `void (*)(void)`
-					out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
-					break;
-				case TypeDecl::Ttype:
-					assertf( false, "Ttype parameters are not currently allowed as parameters to generic types." );
-					break;
-				default:
-					assertf( false, "Unhandled type parameter kind" );
-					break;
-			}
-		}
-
-		assertf( baseParam == baseParams.end() && param == params.end(), "Type parameters should match type variables" );
-		return gt;
-	}
-
-	/// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out
-	void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs,
-							std::list< Declaration* >& out ) {
-		// substitute types into new members
-		TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
-		for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) {
-			Declaration *newMember = (*member)->clone();
-			subs.apply(newMember);
-			out.push_back( newMember );
-		}
-	}
-
-	/// Substitutes types of members according to baseParams => typeSubs, working in-place
-	void substituteMembers( std::list< Declaration* >& members, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs ) {
-		// substitute types into new members
-		TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
-		for ( std::list< Declaration* >::iterator member = members.begin(); member != members.end(); ++member ) {
-			subs.apply(*member);
-		}
-	}
-
-	/// Strips the instances's type parameters
-	void stripInstParams( ReferenceToType *inst ) {
-		deleteAll( inst->get_parameters() );
-		inst->get_parameters().clear();
-	}
-
-	template< typename AggrInst >
-	static AggrInst * asForward( AggrInst * decl ) {
-		if ( !decl->body ) {
-			return nullptr;
-		}
-		decl = decl->clone();
-		decl->body = false;
-		deleteAll( decl->members );
-		decl->members.clear();
-		return decl;
-	}
-
-	void GenericInstantiator::stripDtypeParams( AggregateDecl *base, std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs ) {
-		substituteMembers( base->get_members(), baseParams, typeSubs );
-
-		// xxx - can't delete type parameters because they may have assertions that are used
-		// deleteAll( baseParams );
-		baseParams.clear();
-
-		dtypeStatics.insert( base );
-	}
-
-	/// xxx - more or less copied from box -- these should be merged with those somehow...
-	void GenericInstantiator::replaceParametersWithConcrete( std::list< Expression* >& params ) {
-		for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
-			TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
-			assertf(paramType, "Aggregate parameters should be type expressions");
-			paramType->set_type( replaceWithConcrete( paramType->get_type(), false ) );
-		}
-	}
-
-	Type *GenericInstantiator::replaceWithConcrete( Type *type, bool doClone ) {
-		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
-			if ( env && ! inFunctionType ) {
-				Type *concrete = env->lookup( typeInst->get_name() );
-				if ( concrete ) {
-					return concrete->clone();
-				}
-				else return typeInst->clone();
-			}
-		} else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
-			if ( doClone ) {
-				structType = structType->clone();
-			}
-			replaceParametersWithConcrete( structType->get_parameters() );
-			return structType;
-		} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
-			if ( doClone ) {
-				unionType = unionType->clone();
-			}
-			replaceParametersWithConcrete( unionType->get_parameters() );
-			return unionType;
-		}
-		return type;
-	}
-
-
-	Type* GenericInstantiator::postmutate( StructInstType *inst ) {
-		// exit early if no need for further mutation
-		if ( inst->get_parameters().empty() ) return inst;
-
-		// need to replace type variables to ensure that generic types are instantiated for the return values of polymorphic functions (in particular, for thunks, because they are not [currently] copy constructed).
-		replaceWithConcrete( inst, false );
-
-		// check for an already-instantiatiated dtype-static type
-		if ( dtypeStatics.find( inst->get_baseStruct() ) != dtypeStatics.end() ) {
-			stripInstParams( inst );
-			return inst;
-		}
-
-		// check if type can be concretely instantiated; put substitutions into typeSubs
-		assertf( inst->get_baseParameters(), "Base struct has parameters" );
-		std::list< TypeExpr* > typeSubs;
-		genericType gt = makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs );
-		switch ( gt ) {
-		case genericType::dtypeStatic:
-			stripDtypeParams( inst->get_baseStruct(), *inst->get_baseParameters(), typeSubs );
-			stripInstParams( inst );
-			break;
-
-		case genericType::concrete: {
-			// make concrete instantiation of generic type
-			StructDecl *concDecl = lookup( inst, typeSubs );
-			if ( ! concDecl ) {
-				// set concDecl to new type, insert type declaration into statements to add
-				concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) );
-				concDecl->set_body( inst->get_baseStruct()->has_body() );
-				substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
-				// Forward declare before recursion. (TODO: Only when needed, #199.)
-				insert( inst, typeSubs, concDecl );
-				if ( StructDecl *forwardDecl = asForward( concDecl ) ) {
-					declsToAddBefore.push_back( forwardDecl );
-				}
-				concDecl->acceptMutator( *visitor ); // recursively instantiate members
-				declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first
-			}
-			StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
-			newInst->set_baseStruct( concDecl );
-
-			delete inst;
-			inst = newInst;
-			break;
-		}
-
-		case genericType::dynamic:
-			// do nothing
-			break;
-		}
-
-		deleteAll( typeSubs );
-		return inst;
-	}
-
-	Type* GenericInstantiator::postmutate( UnionInstType *inst ) {
-		// exit early if no need for further mutation
-		if ( inst->get_parameters().empty() ) return inst;
-
-		// check for an already-instantiatiated dtype-static type
-		if ( dtypeStatics.find( inst->get_baseUnion() ) != dtypeStatics.end() ) {
-			stripInstParams( inst );
-			return inst;
-		}
-
-		// check if type can be concretely instantiated; put substitutions into typeSubs
-		assert( inst->get_baseParameters() && "Base union has parameters" );
-		std::list< TypeExpr* > typeSubs;
-		genericType gt = makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs );
-		switch ( gt ) {
-		case genericType::dtypeStatic:
-			stripDtypeParams( inst->get_baseUnion(), *inst->get_baseParameters(), typeSubs );
-			stripInstParams( inst );
-			break;
-
-		case genericType::concrete:
-		{
-			// make concrete instantiation of generic type
-			UnionDecl *concDecl = lookup( inst, typeSubs );
-			if ( ! concDecl ) {
-				// set concDecl to new type, insert type declaration into statements to add
-				concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) );
-				concDecl->set_body( inst->get_baseUnion()->has_body() );
-				substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
-				// Forward declare before recursion. (TODO: Only when needed, #199.)
-				insert( inst, typeSubs, concDecl );
-				if ( UnionDecl *forwardDecl = asForward( concDecl ) ) {
-					declsToAddBefore.push_back( forwardDecl );
-				}
-				concDecl->acceptMutator( *visitor ); // recursively instantiate members
-				declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first
-			}
-			UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
-			newInst->set_baseUnion( concDecl );
-
-			delete inst;
-			inst = newInst;
-			break;
-		}
-		case genericType::dynamic:
-			// do nothing
-			break;
-		}
-
-		deleteAll( typeSubs );
-		return inst;
-	}
-
-	namespace {
-		bool isGenericType( Type * t ) {
-			if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) {
-				return ! inst->parameters.empty();
-			} else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {
-				return ! inst->parameters.empty();
-			}
-			return false;
-		}
-	}
-
-	void GenericInstantiator::premutate( MemberExpr * memberExpr ) {
-		GuardValue( memberIndex );
-		memberIndex = -1;
-		if ( isGenericType( memberExpr->aggregate->result ) ) {
-			// find the location of the member
-			AggregateDecl * aggr = memberExpr->aggregate->result->getAggr();
-			std::list< Declaration * > & members = aggr->members;
-			memberIndex = std::distance( members.begin(), std::find( members.begin(), members.end(), memberExpr->member ) );
-			assertf( memberIndex < (int)members.size(), "Could not find member %s in generic type %s", toString( memberExpr->member ).c_str(), toString( memberExpr->aggregate ).c_str() );
-		}
-	}
-
-	Expression * GenericInstantiator::postmutate( MemberExpr * memberExpr ) {
-		if ( memberIndex != -1 ) {
-			// using the location from the generic type, find the member in the instantiation and rebuild the member expression
-			AggregateDecl * aggr = memberExpr->aggregate->result->getAggr();
-			assertf( memberIndex < (int)aggr->members.size(), "Instantiation somehow has fewer members than the generic type." );
-			Declaration * member = *std::next( aggr->members.begin(), memberIndex );
-			assertf( member->name == memberExpr->member->name, "Instantiation has different member order than the generic type. %s / %s", toString( member ).c_str(), toString( memberExpr->member ).c_str() );
-			DeclarationWithType * field = strict_dynamic_cast< DeclarationWithType * >( member );
-			MemberExpr * ret = new MemberExpr( field, memberExpr->aggregate->clone() );
-			ResolvExpr::adjustExprType( ret->result ); // pointer decay
-			std::swap( ret->env, memberExpr->env );
-			delete memberExpr;
-			return ret;
-		}
-		return memberExpr;
-	}
-
-	void GenericInstantiator::beginScope() {
-		instantiations.beginScope();
-	}
-
-	void GenericInstantiator::endScope() {
-		instantiations.endScope();
-	}
-
-	template< typename AggrInst >
-	Expression * FixDtypeStatic::fixMemberExpr( AggrInst * inst, MemberExpr * memberExpr ) {
-		// need to cast dtype-static member expressions to their actual type before that type is erased.
-		// NOTE: the casts here have the third argument (isGenerated) set to false so that these casts persist until Box, where they are needed.
-		auto & baseParams = *inst->get_baseParameters();
-		if ( isDtypeStatic( baseParams ) ) {
-			if ( ! ResolvExpr::typesCompatible( memberExpr->result, memberExpr->member->get_type(), SymTab::Indexer() ) ) {
-				// type of member and type of expression differ
-				Type * concType = memberExpr->result->clone();
-				if ( isLvalueArg ) {
-					// result must be C lvalue, so make a new reference variable with the correct actual type to replace the member expression
-					//   forall(dtype T)
-					//   struct Ptr {
-					//     T * x
-					//   };
-					//   Ptr(int) p;
-					//   int i;
-					//   p.x = &i;
-					// becomes
-					//   int *& _dtype_static_member_0 = (int **)&p.x;
-					//   _dtype_static_member_0 = &i;
-					// Note: this currently creates more temporaries than is strictly necessary, since it does not check for duplicate uses of the same member expression.
-					static UniqueName tmpNamer( "_dtype_static_member_" );
-					Expression * init = new CastExpr( new AddressExpr( memberExpr ), new PointerType( Type::Qualifiers(), concType->clone() ), false );
-					ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), new ReferenceType( Type::Qualifiers(), concType ), new SingleInit( init ) );
-					stmtsToAddBefore.push_back( new DeclStmt( tmp ) );
-					return new VariableExpr( tmp );
-				} else {
-					// can simply add a cast to actual type
-					return new CastExpr( memberExpr, concType, false );
-				}
-			}
-		}
-		return memberExpr;
-	}
-
-	Expression * FixDtypeStatic::postmutate( MemberExpr * memberExpr ) {
-		Type * aggrType = memberExpr->aggregate->result;
-		if ( isGenericType( aggrType ) ) {
-			if ( StructInstType * inst = dynamic_cast< StructInstType * >( aggrType ) ) {
-				return fixMemberExpr( inst, memberExpr );
-			} else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( aggrType ) ) {
-				return fixMemberExpr( inst, memberExpr );
-			}
-		}
-		return memberExpr;
-	}
-
-	void FixDtypeStatic::premutate( ApplicationExpr * appExpr ) {
-		GuardValue( isLvalueArg );
-		isLvalueArg = false;
-		DeclarationWithType * function = InitTweak::getFunction( appExpr );
-		if ( function->linkage == LinkageSpec::Intrinsic && CodeGen::isAssignment( function->name ) ) {
-			// explicitly visit children because only the first argument must be a C lvalue.
-			visit_children = false;
-			appExpr->env = maybeMutate( appExpr->env, *visitor );
-			appExpr->result = maybeMutate( appExpr->result, *visitor );
-			appExpr->function = maybeMutate( appExpr->function, *visitor );
-			isLvalueArg = true;
-			for ( Expression * arg : appExpr->args ) {
-				arg = maybeMutate( arg, *visitor );
-				isLvalueArg = false;
-			}
-		}
-	}
-
-	void FixDtypeStatic::premutate( AddressExpr * ) {
-		// argument of & must be C lvalue
-		GuardValue( isLvalueArg );
-		isLvalueArg = true;
-	}
-} // namespace GenPoly
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/GenPoly/Lvalue.cc
===================================================================
--- src/GenPoly/Lvalue.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,573 +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.
-//
-// Lvalue.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon May 16 14:09:00 2022
-// Update Count     : 8
-//
-
-#include <cassert>                       // for strict_dynamic_cast
-#include <string>                        // for string
-
-#include "Common/ToString.hpp"           // for toCString
-#include "Common/UniqueName.h"
-#include "Common/PassVisitor.h"
-#include "GenPoly.h"                     // for isPolyType
-#include "Lvalue.h"
-
-#include "InitTweak/InitTweak.h"
-#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
-#include "ResolvExpr/Unify.h"            // for unify
-#include "ResolvExpr/typeops.h"
-#include "SymTab/Indexer.h"              // for Indexer
-#include "SynTree/LinkageSpec.h"         // for Spec, isBuiltin, Intrinsic
-#include "SynTree/Declaration.h"         // for Declaration, FunctionDecl
-#include "SynTree/Expression.h"          // for Expression, ConditionalExpr
-#include "SynTree/Mutator.h"             // for mutateAll, Mutator
-#include "SynTree/Statement.h"           // for ReturnStmt, Statement (ptr o...
-#include "SynTree/Type.h"                // for PointerType, Type, FunctionType
-#include "SynTree/Visitor.h"             // for Visitor, acceptAll
-#include "Validate/FindSpecialDecls.h"   // for dereferenceOperator
-
-#if 0
-#define PRINT(x) x
-#else
-#define PRINT(x)
-#endif
-
-namespace GenPoly {
-	namespace {
-		// TODO: fold this into the general createDeref function??
-		Expression * mkDeref( Expression * arg ) {
-			if ( Validate::dereferenceOperator ) {
-				// note: reference depth can be arbitrarily deep here, so peel off the outermost pointer/reference, not just pointer because they are effecitvely equivalent in this pass
-				VariableExpr * deref = new VariableExpr( Validate::dereferenceOperator );
-				deref->result = new PointerType( Type::Qualifiers(), deref->result );
-				Type * base = InitTweak::getPointerBase( arg->result );
-				assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->result ).c_str() );
-				ApplicationExpr * ret = new ApplicationExpr( deref, { arg } );
-				delete ret->result;
-				ret->result = base->clone();
-				return ret;
-			} else {
-				return UntypedExpr::createDeref( arg );
-			}
-		}
-
-		struct ReferenceConversions final : public WithStmtsToAdd, public WithGuards {
-			Expression * postmutate( CastExpr * castExpr );
-			Expression * postmutate( AddressExpr * addrExpr );
-		};
-
-		/// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced.
-		struct FixIntrinsicArgs final {
-			Expression * postmutate( ApplicationExpr * appExpr );
-		};
-
-		struct FixIntrinsicResult final : public WithGuards {
-			enum {
-				NoSkip,
-				Skip,
-				SkipInProgress
-			} skip = NoSkip;
-
-			void premutate( AsmExpr * ) { GuardValue( skip ); skip = Skip; }
-			void premutate( ApplicationExpr * ) { GuardValue( skip ); skip = (skip == Skip) ? SkipInProgress : NoSkip; }
-
-
-			Expression * postmutate( ApplicationExpr * appExpr );
-			void premutate( FunctionDecl * funcDecl );
-			bool inIntrinsic = false;
-		};
-
-		/// Replace reference types with pointer types
-		struct ReferenceTypeElimination final {
-			Type * postmutate( ReferenceType * refType );
-		};
-
-		/// GCC-like Generalized Lvalues (which have since been removed from GCC)
-		/// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
-		/// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
-		struct GeneralizedLvalue final : public WithVisitorRef<GeneralizedLvalue> {
-			Expression * postmutate( AddressExpr * addressExpr );
-			Expression * postmutate( MemberExpr * memExpr );
-
-			template<typename Func>
-			Expression * applyTransformation( Expression * expr, Expression * arg, Func mkExpr );
-		};
-
-		/// Removes redundant &*/*& pattern that this pass can generate
-		struct CollapseAddrDeref final {
-			Expression * postmutate( AddressExpr * addressExpr );
-			Expression * postmutate( ApplicationExpr * appExpr );
-		};
-
-		struct AddrRef final : public WithGuards, public WithVisitorRef<AddrRef>, public WithShortCircuiting {
-			void premutate( AddressExpr * addrExpr );
-			Expression * postmutate( AddressExpr * addrExpr );
-			void premutate( Expression * expr );
-			void premutate( ApplicationExpr * appExpr );
-			void premutate( SingleInit * init );
-
-			void handleNonAddr( Expression * );
-
-			bool first = true;
-			bool current = false;
-			int refDepth = 0;
-			bool addCast = false;
-		};
-	} // namespace
-
-	// Stored elsewhere (Lvalue2, initially false).
-	extern bool referencesEliminated;
-
-	void convertLvalue( std::list< Declaration* > & translationUnit ) {
-		PassVisitor<ReferenceConversions> refCvt;
-		PassVisitor<ReferenceTypeElimination> elim;
-		PassVisitor<GeneralizedLvalue> genLval;
-		PassVisitor<FixIntrinsicArgs> fixer;
-		PassVisitor<CollapseAddrDeref> collapser;
-		PassVisitor<AddrRef> addrRef;
-		PassVisitor<FixIntrinsicResult> intrinsicResults;
-		mutateAll( translationUnit, intrinsicResults );
-		mutateAll( translationUnit, addrRef );
-		mutateAll( translationUnit, refCvt );
-		mutateAll( translationUnit, fixer );
-		mutateAll( translationUnit, collapser );
-		mutateAll( translationUnit, genLval );
-		mutateAll( translationUnit, elim );  // last because other passes need reference types to work
-
-		// from this point forward, no other pass should create reference types.
-		referencesEliminated = true;
-	}
-
-	Expression * generalizedLvalue( Expression * expr ) {
-		PassVisitor<GeneralizedLvalue> genLval;
-		return expr->acceptMutator( genLval );
-	}
-
-	namespace {
-		// true for intrinsic function calls that return an lvalue in C
-		bool isIntrinsicReference( Expression * expr ) {
-			// known intrinsic-reference prelude functions
-			static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
-			if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
-				std::string fname = InitTweak::getFunctionName( untyped );
-				return lvalueFunctions.count(fname);
-			} else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
-				if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
-					return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name);
-				}
-			}
-			return false;
-		}
-
-		Expression * FixIntrinsicResult::postmutate( ApplicationExpr * appExpr ) {
-			if ( skip != SkipInProgress && isIntrinsicReference( appExpr ) ) {
-				// eliminate reference types from intrinsic applications - now they return lvalues
-				ReferenceType * result = strict_dynamic_cast< ReferenceType * >( appExpr->result );
-				appExpr->result = result->base->clone();
-				if ( ! inIntrinsic ) {
-					// when not in an intrinsic function, add a cast to
-					// don't add cast when in an intrinsic function, since they already have the cast
-					Expression * ret = new CastExpr( appExpr, result );
-					std::swap( ret->env, appExpr->env );
-					return ret;
-				}
-				delete result;
-			}
-			return appExpr;
-		}
-
-		void FixIntrinsicResult::premutate( FunctionDecl * funcDecl ) {
-			GuardValue( inIntrinsic );
-			inIntrinsic = funcDecl->linkage == LinkageSpec::Intrinsic;
-		}
-
-		Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
-			// intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
-			if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
-				FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
-				assertf( ftype, "Function declaration does not have function type." );
-				// can be of differing lengths only when function is variadic
-				assertf( ftype->parameters.size() == appExpr->args.size() || ftype->isVarArgs, "ApplicationExpr args do not match formal parameter type." );
-
-
-				unsigned int i = 0;
-				const unsigned int end = ftype->parameters.size();
-
-				/// The for loop may eagerly dereference the iterators and fail on empty lists
-				if(i == end) { return appExpr; }
-				for ( auto p : unsafe_group_iterate( appExpr->args, ftype->parameters ) ) {
-					Expression *& arg = std::get<0>( p );
-					Type * formal = std::get<1>( p )->get_type();
-					PRINT(
-						std::cerr << "pair<0>: " << arg << std::endl;
-						std::cerr << " -- " << arg->result << std::endl;
-						std::cerr << "pair<1>: " << formal << std::endl;
-					)
-					if ( dynamic_cast<ReferenceType*>( formal ) ) {
-						PRINT(
-							std::cerr << "===formal is reference" << std::endl;
-						)
-						// TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation.
-
-						if ( function->linkage != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
-							// needed for definition of prelude functions, etc.
-							// if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
-
-							// NOTE: previously, this condition fixed
-							//   void f(int *&);
-							//   int & x = ...;
-							//   f(&x);
-							// But now this is taken care of by a reference cast added by AddrRef. Need to find a new
-							// example or remove this branch.
-
-							PRINT(
-								std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
-							)
-							arg = new AddressExpr( arg );
-						// } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) {
-						} else if ( function->linkage == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
-							// argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument
-							PRINT(
-								std::cerr << "===is non-intrinsic arg in intrinsic call - adding deref to arg" << std::endl;
-							)
-							Type * baseType = InitTweak::getPointerBase( arg->result );
-							assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->result ).c_str() );
-							PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
-							delete arg->result;
-							arg->result = ptrType;
-							arg = mkDeref( arg );
-							// assertf( arg->result->referenceDepth() == 0, "Reference types should have been eliminated from intrinsic function calls, but weren't: %s", toCString( arg->result ) );
-						}
-					}
-					++i;
-					if (i == end) break;
-				}
-			}
-			return appExpr;
-		}
-
-		// idea: &&&E: get outer &, inner &
-		// at inner &, record depth D of reference type of argument of &
-		// at outer &, add D derefs.
-		void AddrRef::handleNonAddr( Expression * ) {
-			// non-address-of: reset status variables:
-			// * current expr is NOT the first address-of expr in an address-of chain
-			// * next seen address-of expr IS the first in the chain.
-			GuardValue( current );
-			GuardValue( first );
-			current = false;
-			first = true;
-		}
-
-		void AddrRef::premutate( Expression * expr ) {
-			handleNonAddr( expr );
-			GuardValue( addCast );
-			addCast = false;
-		}
-
-		void AddrRef::premutate( AddressExpr * ) {
-			GuardValue( current );
-			GuardValue( first );
-			current = first; // is this the first address-of in the chain?
-			first = false;   // from here out, no longer possible for next address-of to be first in chain
-			if ( current ) { // this is the outermost address-of in a chain
-				GuardValue( refDepth );
-				refDepth = 0;  // set depth to 0 so that postmutate can find the innermost address-of easily
-			}
-		}
-
-		Expression * AddrRef::postmutate( AddressExpr * addrExpr ) {
-			PRINT( std::cerr << "addr ref at " << addrExpr << std::endl; )
-			if ( refDepth == 0 ) {
-				PRINT( std::cerr << "depth 0, get new depth..." << std::endl; )
-				// this is the innermost address-of in a chain, record depth D
-				if ( ! isIntrinsicReference( addrExpr->arg ) ) {
-					// try to avoid ?[?]
-					// xxx - is this condition still necessary? intrinsicReferences should have a cast around them at this point, so I don't think this condition ever fires.
-					refDepth = addrExpr->arg->result->referenceDepth();
-					PRINT( std::cerr << "arg not intrinsic reference, new depth is: " << refDepth << std::endl; )
-				} else {
-					assertf( false, "AddrRef : address-of should not have intrinsic reference argument: %s", toCString( addrExpr->arg ) );
-				}
-			}
-			if ( current ) { // this is the outermost address-of in a chain
-				PRINT( std::cerr << "current, depth is: " << refDepth << std::endl; )
-				Expression * ret = addrExpr;
-				while ( refDepth ) {
-					// add one dereference for each
-					ret = mkDeref( ret );
-					refDepth--;
-				}
-
-				// if addrExpr depth is 0, then the result is a pointer because the arg was depth 1 and not lvalue.
-				// This means the dereference result is not a reference, is lvalue, and one less pointer depth than
-				// the addrExpr. Thus the cast is meaningless.
-				// TODO: One thing to double check is whether it is possible for the types to differ outside of the single
-				// pointer level (i.e. can the base type of addrExpr differ from the type of addrExpr-arg?).
-				// If so then the cast might need to be added, conditional on a more sophisticated check.
-				if ( addCast && addrExpr->result->referenceDepth() != 0 ) {
-					PRINT( std::cerr << "adding cast to " << addrExpr->result << std::endl; )
-					return new CastExpr( ret, addrExpr->result->clone() );
-				}
-				return ret;
-			}
-			PRINT( std::cerr << "not current..." << std::endl; )
-			return addrExpr;
-		}
-
-		void AddrRef::premutate( ApplicationExpr * appExpr ) {
-			visit_children = false;
-			GuardValue( addCast );
-			handleNonAddr( appExpr );
-			for ( Expression *& arg : appExpr->args ) {
-				// each argument with address-of requires a cast
-				addCast = true;
-				arg = arg->acceptMutator( *visitor );
-			}
-		}
-
-		void AddrRef::premutate( SingleInit * ) {
-			GuardValue( addCast );
-			// each initialization context with address-of requires a cast
-			addCast = true;
-		}
-
-
-		Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) {
-			// Inner expression may have been lvalue to reference conversion, which becomes an address expression.
-			// In this case, remove the outer address expression and return the argument.
-			// TODO: It's possible that this might catch too much and require a more sophisticated check.
-			return addrExpr;
-		}
-
-		Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) {
-			// xxx - is it possible to convert directly between reference types with a different base? E.g.,
-			//   int x;
-			//   (double&)x;
-			// At the moment, I am working off of the assumption that this is illegal, thus the cast becomes redundant
-			// after this pass, so trash the cast altogether. If that changes, care must be taken to insert the correct
-			// pointer casts in the right places.
-
-			// Note: reference depth difference is the determining factor in what code is run, rather than whether something is
-			// reference type or not, since conversion still needs to occur when both types are references that differ in depth.
-
-			Type * destType = castExpr->result;
-			Type * srcType = castExpr->arg->result;
-			assertf( destType, "Cast to no type in: %s", toCString( castExpr ) );
-			assertf( srcType, "Cast from no type in: %s", toCString( castExpr ) );
-			int depth1 = destType->referenceDepth();
-			int depth2 = srcType->referenceDepth();
-			int diff = depth1 - depth2;
-
-			if ( diff > 0 && ! castExpr->arg->get_lvalue() ) {
-				// rvalue to reference conversion -- introduce temporary
-				// know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g.
-				//   (int &&&)3;
-				// becomes
-				//   int __ref_tmp_0 = 3;
-				//   int & __ref_tmp_1 = _&_ref_tmp_0;
-				//   int && __ref_tmp_2 = &__ref_tmp_1;
-				//   &__ref_tmp_2;
-				// the last & comes from the remaining reference conversion code
-				SemanticWarning( castExpr->arg->location, Warning::RvalueToReferenceConversion, toCString( castExpr->arg ) );
-
-				static UniqueName tempNamer( "__ref_tmp_" );
-				ObjectDecl * temp = ObjectDecl::newObject( tempNamer.newName(), castExpr->arg->result->clone(), new SingleInit( castExpr->arg ) );
-				PRINT( std::cerr << "made temp: " << temp << std::endl; )
-				stmtsToAddBefore.push_back( new DeclStmt( temp ) );
-				for ( int i = 0; i < depth1-1; i++ ) { // xxx - maybe this should be diff-1? check how this works with reference type for srcType
-					ObjectDecl * newTemp = ObjectDecl::newObject( tempNamer.newName(), new ReferenceType( Type::Qualifiers(), temp->type->clone() ), new SingleInit( new AddressExpr( new VariableExpr( temp ) ) ) );
-					PRINT( std::cerr << "made temp" << i << ": " << newTemp << std::endl; )
-					stmtsToAddBefore.push_back( new DeclStmt( newTemp ) );
-					temp = newTemp;
-				}
-				// update diff so that remaining code works out correctly
-				castExpr->arg = new VariableExpr( temp );
-				PRINT( std::cerr << "update cast to: " << castExpr << std::endl; )
-				srcType = castExpr->arg->result;
-				depth2 = srcType->referenceDepth();
-				diff = depth1 - depth2;
-				assert( diff == 1 );
-			}
-
-			// handle conversion between different depths
-			PRINT (
-				if ( depth1 || depth2 ) {
-					std::cerr << "destType: " << destType << " / srcType: " << srcType << std::endl;
-					std::cerr << "depth: " << depth1 << " / " << depth2 << std::endl;
-				}
-			)
-			if ( diff > 0 ) {
-				// conversion to type with more depth (e.g. int & -> int &&): add address-of for each level of difference
-				Expression * ret = castExpr->arg;
-				for ( int i = 0; i < diff; ++i ) {
-					ret = new AddressExpr( ret );
-				}
-				if ( castExpr->arg->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) {
-					// must keep cast if cast-to type is different from the actual type
-					castExpr->arg = ret;
-					return castExpr;
-				}
-				ret->env = castExpr->env;
-				delete ret->result;
-				ret->result = castExpr->result;
-				castExpr->env = nullptr;
-				castExpr->arg = nullptr;
-				castExpr->result = nullptr;
-				delete castExpr;
-				return ret;
-			} else if ( diff < 0 ) {
-				// conversion to type with less depth (e.g. int && -> int &): add dereferences for each level of difference
-				diff = -diff; // care only about magnitude now
-				Expression * ret = castExpr->arg;
-				for ( int i = 0; i < diff; ++i ) {
-					ret = mkDeref( ret );
-					// xxx - try removing one reference here? actually, looks like mkDeref already does this, so more closely look at the types generated.
-				}
-				if ( ! ResolvExpr::typesCompatibleIgnoreQualifiers( destType->stripReferences(), srcType->stripReferences(), SymTab::Indexer() ) ) {
-					// must keep cast if types are different
-					castExpr->arg = ret;
-					return castExpr;
-				}
-				ret->env = castExpr->env;
-				delete ret->result;
-				ret->result = castExpr->result;
-				assert( ret->get_lvalue() ); // ensure result is lvalue
-				castExpr->env = nullptr;
-				castExpr->arg = nullptr;
-				castExpr->result = nullptr;
-				delete castExpr;
-				return ret;
-			} else {
-				assert( diff == 0 );
-				// conversion between references of the same depth
-				if ( ResolvExpr::typesCompatible( castExpr->result, castExpr->arg->result, SymTab::Indexer() ) && castExpr->isGenerated ) {
-					// Remove useless generated casts
-					PRINT(
-						std::cerr << "types are compatible, removing cast: " << castExpr << std::endl;
-						std::cerr << "-- " << castExpr->result << std::endl;
-						std::cerr << "-- " << castExpr->arg->result << std::endl;
-					)
-					Expression * ret = castExpr->arg;
-					castExpr->arg = nullptr;
-					std::swap( castExpr->env, ret->env );
-					delete castExpr;
-					return ret;
-				}
-				return castExpr;
-			}
-		}
-
-		Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) {
-			Type * base = refType->base;
-			Type::Qualifiers qualifiers = refType->get_qualifiers();
-			refType->base = nullptr;
-			delete refType;
-			return new PointerType( qualifiers, base );
-		}
-
-		template<typename Func>
-		Expression * GeneralizedLvalue::applyTransformation( Expression * expr, Expression * arg, Func mkExpr ) {
-			if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( arg ) ) {
-				Expression * arg1 = commaExpr->arg1->clone();
-				Expression * arg2 = commaExpr->arg2->clone();
-				Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) );
-				ret->env = expr->env;
-				expr->env = nullptr;
-				delete expr;
-				return ret;
-			} else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) {
-				Expression * arg1 = condExpr->arg1->clone();
-				Expression * arg2 = condExpr->arg2->clone();
-				Expression * arg3 = condExpr->arg3->clone();
-				ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) );
-				ret->env = expr->env;
-				expr->env = nullptr;
-				delete expr;
-
-				// conditional expr type may not be either of the argument types, need to unify
-				using namespace ResolvExpr;
-				Type* commonType = nullptr;
-				TypeEnvironment newEnv;
-				AssertionSet needAssertions, haveAssertions;
-				OpenVarSet openVars;
-				unify( ret->arg2->result, ret->arg3->result, newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType );
-				ret->result = commonType ? commonType : ret->arg2->result->clone();
-				return ret;
-			}
-			return expr;
-		}
-
-		Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) {
-			return applyTransformation( memExpr, memExpr->aggregate, [=]( Expression * aggr ) { return new MemberExpr( memExpr->member, aggr ); } );
-		}
-
-		Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) {
-			return applyTransformation( addrExpr, addrExpr->arg, []( Expression * arg ) { return new AddressExpr( arg ); } );
-		}
-
-		Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) {
-			Expression * arg = addrExpr->arg;
-			if ( isIntrinsicReference( arg ) ) {
-				std::string fname = InitTweak::getFunctionName( arg );
-				if ( fname == "*?" ) {
-					Expression *& arg0 = InitTweak::getCallArg( arg, 0 );
-					Expression * ret = arg0;
-					ret->set_env( addrExpr->env );
-					arg0 = nullptr;
-					addrExpr->env = nullptr;
-					delete addrExpr;
-					return ret;
-				}
-			} else if ( CastExpr * castExpr = dynamic_cast< CastExpr * > ( arg ) ) {
-				// need to move cast to pointer type out a level since address of pointer
-				// is not valid C code (can be introduced in prior passes, e.g., InstantiateGeneric)
-				if ( InitTweak::getPointerBase( castExpr->result ) ) {
-					addrExpr->arg = castExpr->arg;
-					castExpr->arg = addrExpr;
-					castExpr->result = new PointerType( Type::Qualifiers(), castExpr->result );
-					return castExpr;
-				}
-			}
-			return addrExpr;
-		}
-
-		Expression * CollapseAddrDeref::postmutate( ApplicationExpr * appExpr ) {
-			if ( isIntrinsicReference( appExpr ) ) {
-				std::string fname = InitTweak::getFunctionName( appExpr );
-				if ( fname == "*?" ) {
-					Expression * arg = InitTweak::getCallArg( appExpr, 0 );
-					// xxx - this isn't right, because it can remove casts that should be there...
-					// while ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) {
-					// 	arg = castExpr->get_arg();
-					// }
-					if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) {
-						Expression * ret = addrExpr->arg;
-						ret->env = appExpr->env;
-						addrExpr->arg = nullptr;
-						appExpr->env = nullptr;
-						delete appExpr;
-						return ret;
-					}
-				}
-			}
-			return appExpr;
-		}
-	} // namespace
-} // namespace GenPoly
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/GenPoly/ScrubTyVars.cc
===================================================================
--- src/GenPoly/ScrubTyVars.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/GenPoly/ScrubTyVars.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -21,97 +21,6 @@
 #include "ScrubTyVars.h"
 #include "SymTab/Mangler.h"             // for mangleType
-#include "SynTree/Declaration.h"        // for TypeDecl, TypeDecl::Data, Typ...
-#include "SynTree/Expression.h"         // for Expression (ptr only), NameExpr
-#include "SynTree/Mutator.h"            // for Mutator
-#include "SynTree/Type.h"               // for PointerType, TypeInstType, Type
 
 namespace GenPoly {
-	Type * ScrubTyVars::postmutate( TypeInstType * typeInst ) {
-		if ( ! tyVars ) {
-			if ( typeInst->get_isFtype() ) {
-				delete typeInst;
-				return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
-			} else {
-				PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
-				delete typeInst;
-				return ret;
-			}
-		}
-
-		TyVarMap::const_iterator tyVar = tyVars->find( typeInst->name );
-		if ( tyVar != tyVars->end() ) {
-			switch ( tyVar->second.kind ) {
-			  case TypeDecl::Dtype:
-			  case TypeDecl::Ttype:
-				{
-					PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
-					delete typeInst;
-					return ret;
-				}
-			  case TypeDecl::Ftype:
-				delete typeInst;
-				return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
-			  default:
-				assertf(false, "Unhandled tyvar kind: %d", tyVar->second.kind);
-			} // switch
-		} // if
-		return typeInst;
-	}
-
-	Type * ScrubTyVars::mutateAggregateType( Type * ty ) {
-		if ( shouldScrub( ty ) ) {
-			PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) );
-			delete ty;
-			return ret;
-		}
-		return ty;
-	}
-
-	Type * ScrubTyVars::postmutate( StructInstType * structInst ) {
-		return mutateAggregateType( structInst );
-	}
-
-	Type * ScrubTyVars::postmutate( UnionInstType * unionInst ) {
-		return mutateAggregateType( unionInst );
-	}
-
-	void ScrubTyVars::primeBaseScrub( Type * type ) {
-		// need to determine whether type needs to be scrubbed to determine whether
-		// automatic recursion is necessary
-		if ( Type * t = shouldScrub( type ) ) {
-			visit_children = false;
-			GuardValue( dynType );
-			dynType = t;
-		}
-	}
-
-	Expression * ScrubTyVars::postmutate( SizeofExpr * szeof ) {
-		// sizeof( T ) => _sizeof_T parameter, which is the size of T
-		if ( dynType ) {
-			Expression *expr = new NameExpr( sizeofName( mangleType( dynType ) ) );
-			return expr;
-		} // if
-		return szeof;
-	}
-
-	Expression * ScrubTyVars::postmutate( AlignofExpr * algnof ) {
-		// alignof( T ) => _alignof_T parameter, which is the alignment of T
-		if ( dynType ) {
-			Expression *expr = new NameExpr( alignofName( mangleType( dynType ) ) );
-			return expr;
-		} // if
-		return algnof;
-	}
-
-	Type * ScrubTyVars::postmutate( PointerType * pointer ) {
-		if ( dynType ) {
-			Type * ret = dynType->acceptMutator( *visitor );
-			ret->get_qualifiers() |= pointer->get_qualifiers();
-			pointer->base = nullptr;
-			delete pointer;
-			return ret;
-		}
-		return pointer;
-	}
 
 namespace {
Index: src/GenPoly/ScrubTyVars.h
===================================================================
--- src/GenPoly/ScrubTyVars.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/GenPoly/ScrubTyVars.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -19,93 +19,7 @@
 
 #include "AST/Fwd.hpp"        // for Node
-#include "Common/PassVisitor.h"
 #include "GenPoly.h"          // for TyVarMap, isPolyType, isDynType
-#include "SynTree/Mutator.h"  // for Mutator
-#include "SynTree/Type.h"     // for Type (ptr only), PointerType (ptr only)
-
-class AlignofExpr;
-class Expression;
-class SizeofExpr;
 
 namespace GenPoly {
-	struct ScrubTyVars : public WithVisitorRef<ScrubTyVars>, public WithShortCircuiting, public WithGuards {
-		/// Whether to scrub all type variables from the provided map, dynamic type variables from the provided map, or all type variables
-		enum ScrubMode { FromMap, DynamicFromMap, All };
-
-		ScrubTyVars() : tyVars(nullptr), mode( All ) {}
-
-		ScrubTyVars( const TyVarMap &tyVars, ScrubMode mode = FromMap ): tyVars( &tyVars ), mode( mode ) {}
-
-	public:
-		/// For all polymorphic types with type variables in `tyVars`, replaces generic types, dtypes, and ftypes with the appropriate void type,
-		/// and sizeof/alignof expressions with the proper variable
-		template< typename SynTreeClass >
-		static SynTreeClass *scrub( SynTreeClass *target, const TyVarMap &tyVars );
-
-		/// For all dynamic-layout types with type variables in `tyVars`, replaces generic types, dtypes, and ftypes with the appropriate void type,
-		/// and sizeof/alignof expressions with the proper variable
-		template< typename SynTreeClass >
-		static SynTreeClass *scrubDynamic( SynTreeClass *target, const TyVarMap &tyVars );
-
-		/// For all polymorphic types, replaces generic types, dtypes, and ftypes with the appropriate void type,
-		/// and sizeof/alignof expressions with the proper variable
-		template< typename SynTreeClass >
-		static SynTreeClass *scrubAll( SynTreeClass *target );
-
-		/// determine if children should be visited based on whether base type should be scrubbed.
-		void primeBaseScrub( Type * );
-
-		void premutate( TypeInstType * ) { visit_children = false; }
-		void premutate( StructInstType * ) { visit_children = false; }
-		void premutate( UnionInstType * ) { visit_children = false; }
-		void premutate( SizeofExpr * szeof ) { primeBaseScrub( szeof->type ); }
-		void premutate( AlignofExpr * algnof ) { primeBaseScrub( algnof->type ); }
-		void premutate( PointerType * pointer ) { primeBaseScrub( pointer->base ); }
-
-		Type * postmutate( TypeInstType * typeInst );
-		Type * postmutate( StructInstType * structInst );
-		Type * postmutate( UnionInstType * unionInst );
-		Expression * postmutate( SizeofExpr * szeof );
-		Expression * postmutate( AlignofExpr * algnof );
-		Type * postmutate( PointerType * pointer );
-
-	  private:
-		/// Returns the type if it should be scrubbed, NULL otherwise.
-		Type* shouldScrub( Type *ty ) {
-			switch ( mode ) {
-			case FromMap: return isPolyType( ty, *tyVars );
-			case DynamicFromMap: return isDynType( ty, *tyVars );
-			case All: return isPolyType( ty );
-			}
-			assert(false); return nullptr; // unreachable
-			// return dynamicOnly ? isDynType( ty, tyVars ) : isPolyType( ty, tyVars );
-		}
-
-		/// Mutates (possibly generic) aggregate types appropriately
-		Type* mutateAggregateType( Type *ty );
-
-		const TyVarMap *tyVars;  ///< Type variables to scrub
-		ScrubMode mode;          ///< which type variables to scrub? [FromMap]
-
-		Type * dynType = nullptr; ///< result of shouldScrub
-	};
-
-	template< typename SynTreeClass >
-	SynTreeClass * ScrubTyVars::scrub( SynTreeClass *target, const TyVarMap &tyVars ) {
-		PassVisitor<ScrubTyVars> scrubber( tyVars );
-		return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
-	}
-
-	template< typename SynTreeClass >
-	SynTreeClass * ScrubTyVars::scrubDynamic( SynTreeClass *target, const TyVarMap &tyVars ) {
-		PassVisitor<ScrubTyVars> scrubber( tyVars, ScrubTyVars::DynamicFromMap );
-		return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
-	}
-
-	template< typename SynTreeClass >
-	SynTreeClass * ScrubTyVars::scrubAll( SynTreeClass *target ) {
-		PassVisitor<ScrubTyVars> scrubber;
-		return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
-	}
 
 // ScrubMode and scrubTypeVarsBase are internal.
Index: c/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,338 +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.
-//
-// Specialize.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Thr Jul  2 17:42:00 2020
-// Update Count     : 33
-//
-
-#include <cassert>                       // for assert, assertf
-#include <iterator>                      // for back_insert_iterator, back_i...
-#include <map>                           // for _Rb_tree_iterator, _Rb_tree_...
-#include <memory>                        // for unique_ptr
-#include <string>                        // for string
-#include <tuple>                         // for get
-#include <utility>                       // for pair
-
-#include "Common/PassVisitor.h"
-#include "Common/UniqueName.h"           // for UniqueName
-#include "Common/utility.h"              // for group_iterate
-#include "GenPoly.h"                     // for getFunctionType
-#include "InitTweak/InitTweak.h"         // for isIntrinsicCallExpr
-#include "ResolvExpr/FindOpenVars.h"     // for findOpenVars
-#include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
-#include "Specialize.h"
-#include "SynTree/LinkageSpec.h"         // for C
-#include "SynTree/Attribute.h"           // for Attribute
-#include "SynTree/Declaration.h"         // for FunctionDecl, DeclarationWit...
-#include "SynTree/Expression.h"          // for ApplicationExpr, Expression
-#include "SynTree/Label.h"               // for Label
-#include "SynTree/Mutator.h"             // for mutateAll
-#include "SynTree/Statement.h"           // for CompoundStmt, DeclStmt, Expr...
-#include "SynTree/Type.h"                // for FunctionType, TupleType, Type
-#include "SynTree/TypeSubstitution.h"    // for TypeSubstitution
-#include "SynTree/Visitor.h"             // for Visitor
-
-namespace GenPoly {
-	struct Specialize final : public WithConstTypeSubstitution,
-			public WithDeclsToAdd, public WithVisitorRef<Specialize> {
-		Expression * postmutate( ApplicationExpr *applicationExpr );
-		Expression * postmutate( CastExpr *castExpr );
-
-		void handleExplicitParams( ApplicationExpr *appExpr );
-		Expression * createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams );
-		Expression * doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams );
-
-		std::string paramPrefix = "_p";
-	};
-
-	/// Looks up open variables in actual type, returning true if any of them are bound in the environment or formal type.
-	bool needsPolySpecialization( Type *formalType, Type *actualType, const TypeSubstitution *env ) {
-		if ( env ) {
-			using namespace ResolvExpr;
-			OpenVarSet openVars, closedVars;
-			AssertionSet need, have;
-			findOpenVars( formalType, openVars, closedVars, need, have, false );
-			findOpenVars( actualType, openVars, closedVars, need, have, true );
-			for ( OpenVarSet::const_iterator openVar = openVars.begin(); openVar != openVars.end(); ++openVar ) {
-				Type *boundType = env->lookup( openVar->first );
-				if ( ! boundType ) continue;
-				if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( boundType ) ) {
-					// bound to another type variable
-					if ( closedVars.find( typeInst->get_name() ) == closedVars.end() ) {
-						// bound to a closed variable => must specialize
-						return true;
-					} // if
-				} else {
-					// variable is bound to a concrete type => must specialize
-					return true;
-				} // if
-			} // for
-			// none of the type variables are bound
-			return false;
-		} else {
-			// no env
-			return false;
-		} // if
-	}
-
-	/// True if both types have the same structure, but not necessarily the same types.
-	/// That is, either both types are tuple types with the same size (recursively), or
-	/// both are not tuple types.
-	bool matchingTupleStructure( Type * t1, Type * t2 ) {
-		TupleType * tuple1 = dynamic_cast< TupleType * >( t1 );
-		TupleType * tuple2 = dynamic_cast< TupleType * >( t2 );
-		if ( tuple1 && tuple2 ) {
-			if ( tuple1->size() != tuple2->size() ) return false;
-			for ( auto types : group_iterate( tuple1->get_types(), tuple2->get_types() ) ) {
-				if ( ! matchingTupleStructure( std::get<0>( types ), std::get<1>( types ) ) ) return false;
-			}
-			return true;
-		} else if ( ! tuple1 && ! tuple2 ) return true;
-		return false;
-	}
-
-	// walk into tuple type and find the number of components
-	size_t singleParameterSize( Type * type ) {
-		if ( TupleType * tt = dynamic_cast< TupleType * >( type ) ) {
-			size_t sz = 0;
-			for ( Type * t : *tt ) {
-				sz += singleParameterSize( t );
-			}
-			return sz;
-		} else {
-			return 1;
-		}
-	}
-
-	// find the total number of components in a parameter list
-	size_t functionParameterSize( FunctionType * ftype ) {
-		size_t sz = 0;
-		for ( DeclarationWithType * p : ftype->get_parameters() ) {
-			sz += singleParameterSize( p->get_type() );
-		}
-		return sz;
-	}
-
-	bool needsTupleSpecialization( Type *formalType, Type *actualType ) {
-		// Needs tuple specialization if the structure of the formal type and actual type do not match.
-		// This is the case if the formal type has ttype polymorphism, or if the structure  of tuple types
-		// between the function do not match exactly.
-		if ( FunctionType * fftype = getFunctionType( formalType ) ) {
-			if ( fftype->isTtype() ) return true;
-			// conversion of 0 (null) to function type does not require tuple specialization
-			if ( dynamic_cast< ZeroType * >( actualType ) ) return false;
-			FunctionType * aftype = getFunctionType( actualType->stripReferences() );
-			assertf( aftype, "formal type is a function type, but actual type is not: %s", toString( actualType ).c_str() );
-			// Can't tuple specialize if parameter sizes deeply-differ.
-			if ( functionParameterSize( fftype ) != functionParameterSize( aftype ) ) return false;
-			// tuple-parameter sizes are the same, but actual parameter sizes differ - must tuple specialize
-			if ( fftype->parameters.size() != aftype->parameters.size() ) return true;
-			// total parameter size can be the same, while individual parameters can have different structure
-			for ( auto params : group_iterate( fftype->parameters, aftype->parameters ) ) {
-				DeclarationWithType * formal = std::get<0>(params);
-				DeclarationWithType * actual = std::get<1>(params);
-				if ( ! matchingTupleStructure( formal->get_type(), actual->get_type() ) ) return true;
-			}
-		}
-		return false;
-	}
-
-	bool needsSpecialization( Type *formalType, Type *actualType, const TypeSubstitution *env ) {
-		return needsPolySpecialization( formalType, actualType, env ) || needsTupleSpecialization( formalType, actualType );
-	}
-
-	Expression * Specialize::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) {
-		assertf( actual->result, "attempting to specialize an untyped expression" );
-		if ( needsSpecialization( formalType, actual->get_result(), env ) ) {
-			if ( FunctionType *funType = getFunctionType( formalType ) ) {
-				if ( ApplicationExpr * appExpr = dynamic_cast<ApplicationExpr*>( actual ) ) {
-					return createThunkFunction( funType, appExpr->get_function(), inferParams );
-				} else if ( VariableExpr * varExpr = dynamic_cast<VariableExpr*>( actual ) ) {
-					return createThunkFunction( funType, varExpr, inferParams );
-				} else {
-					// This likely won't work, as anything that could build an ApplicationExpr probably hit one of the previous two branches
-					return createThunkFunction( funType, actual, inferParams );
-				}
-			} else {
-				return actual;
-			} // if
-		} else {
-			return actual;
-		} // if
-	}
-
-	/// restructures the arguments to match the structure of the formal parameters of the actual function.
-	/// [begin, end) are the exploded arguments.
-	template< typename Iterator, typename OutIterator >
-	void structureArg( Type * type, Iterator & begin, Iterator end, OutIterator out ) {
-		if ( TupleType * tuple = dynamic_cast< TupleType * >( type ) ) {
-			std::list< Expression * > exprs;
-			for ( Type * t : *tuple ) {
-				structureArg( t, begin, end, back_inserter( exprs ) );
-			}
-			*out++ = new TupleExpr( exprs );
-		} else {
-			assertf( begin != end, "reached the end of the arguments while structuring" );
-			*out++ = *begin++;
-		}
-	}
-
-	/// explode assuming simple cases: either type is pure tuple (but not tuple expr) or type is non-tuple.
-	template< typename OutputIterator >
-	void explodeSimple( Expression * expr, OutputIterator out ) {
-		if ( TupleType * tupleType = dynamic_cast< TupleType * > ( expr->get_result() ) ) {
-			// tuple type, recursively index into its components
-			for ( unsigned int i = 0; i < tupleType->size(); i++ ) {
-				explodeSimple( new TupleIndexExpr( expr->clone(), i ), out );
-			}
-			delete expr;
-		} else {
-			// non-tuple type - output a clone of the expression
-			*out++ = expr;
-		}
-	}
-
-	/// Generates a thunk that calls `actual` with type `funType` and returns its address
-	Expression * Specialize::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) {
-		static UniqueName thunkNamer( "_thunk" );
-
-		FunctionType *newType = funType->clone();
-		if ( env ) {
-			// it is important to replace only occurrences of type variables that occur free in the
-			// thunk's type
-			env->applyFree( newType );
-		} // if
-		// create new thunk with same signature as formal type (C linkage, empty body)
-		FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), Type::StorageClasses(), LinkageSpec::C, newType, new CompoundStmt() );
-		thunkFunc->fixUniqueId();
-
-		// thunks may be generated and not used - silence warning with attribute
-		thunkFunc->get_attributes().push_back( new Attribute( "unused" ) );
-
-		// Thunks at the global level must be static to avoid collisions between files.
-		// (Conversly thunks inside a function must be unique and not static.)
-		thunkFunc->storageClasses.is_static = !isInFunction();
-
-		// thread thunk parameters into call to actual function, naming thunk parameters as we go
-		UniqueName paramNamer( paramPrefix );
-		ApplicationExpr *appExpr = new ApplicationExpr( actual );
-
-		FunctionType * actualType = getFunctionType( actual->get_result() )->clone();
-		if ( env ) {
-			// need to apply the environment to the actual function's type, since it may itself be polymorphic
-			env->apply( actualType );
-		}
-		std::unique_ptr< FunctionType > actualTypeManager( actualType ); // for RAII
-		std::list< DeclarationWithType * >::iterator actualBegin = actualType->get_parameters().begin();
-		std::list< DeclarationWithType * >::iterator actualEnd = actualType->get_parameters().end();
-
-		std::list< Expression * > args;
-		for ( DeclarationWithType* param : thunkFunc->get_functionType()->get_parameters() ) {
-			// name each thunk parameter and explode it - these are then threaded back into the actual function call.
-			param->set_name( paramNamer.newName() );
-			explodeSimple( new VariableExpr( param ), back_inserter( args ) );
-		}
-
-		// walk parameters to the actual function alongside the exploded thunk parameters and restructure the arguments to match the actual parameters.
-		std::list< Expression * >::iterator argBegin = args.begin(), argEnd = args.end();
-		for ( ; actualBegin != actualEnd; ++actualBegin ) {
-			structureArg( (*actualBegin)->get_type(), argBegin, argEnd, back_inserter( appExpr->get_args() ) );
-		}
-		assertf( argBegin == argEnd, "Did not structure all arguments." );
-
-		appExpr->env = TypeSubstitution::newFromExpr( appExpr, env );
-		if ( inferParams ) {
-			appExpr->inferParams = *inferParams;
-		} // if
-
-		// Handle any specializations that may still be present.
-		{
-			std::string oldParamPrefix = paramPrefix;
-			paramPrefix += "p";
-			std::list< Declaration * > oldDecls;
-			oldDecls.splice( oldDecls.end(), declsToAddBefore );
-
-			appExpr->acceptMutator( *visitor );
-			// Write recursive specializations into the thunk body.
-			for ( Declaration * decl : declsToAddBefore ) {
-				thunkFunc->statements->kids.push_back( new DeclStmt( decl ) );
-			}
-
-			declsToAddBefore = std::move( oldDecls );
-			paramPrefix = oldParamPrefix;
-		}
-
-		// add return (or valueless expression) to the thunk
-		Statement *appStmt;
-		if ( funType->returnVals.empty() ) {
-			appStmt = new ExprStmt( appExpr );
-		} else {
-			appStmt = new ReturnStmt( appExpr );
-		} // if
-		thunkFunc->statements->kids.push_back( appStmt );
-
-		// Add the thunk definition (converted to DeclStmt if appproprate).
-		declsToAddBefore.push_back( thunkFunc );
-		// return address of thunk function as replacement expression
-		return new AddressExpr( new VariableExpr( thunkFunc ) );
-	}
-
-	void Specialize::handleExplicitParams( ApplicationExpr *appExpr ) {
-		// create thunks for the explicit parameters
-		assert( appExpr->function->result );
-		FunctionType *function = getFunctionType( appExpr->function->result );
-		assert( function );
-		std::list< DeclarationWithType* >::iterator formal;
-		std::list< Expression* >::iterator actual;
-		for ( formal = function->get_parameters().begin(), actual = appExpr->get_args().begin(); formal != function->get_parameters().end() && actual != appExpr->get_args().end(); ++formal, ++actual ) {
-			*actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr->inferParams );
-		}
-	}
-
-	Expression * Specialize::postmutate( ApplicationExpr *appExpr ) {
-		if ( ! InitTweak::isIntrinsicCallExpr( appExpr ) ) {
-			// create thunks for the inferred parameters
-			// don't need to do this for intrinsic calls, because they aren't actually passed
-			// need to handle explicit params before inferred params so that explicit params do not recieve a changed set of inferParams (and change them again)
-			// alternatively, if order starts to matter then copy appExpr's inferParams and pass them to handleExplicitParams.
-			handleExplicitParams( appExpr );
-			for ( InferredParams::iterator inferParam = appExpr->inferParams.begin(); inferParam != appExpr->inferParams.end(); ++inferParam ) {
-				inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &inferParam->second.expr->inferParams );
-			}
-		}
-		return appExpr;
-	}
-
-	Expression * Specialize::postmutate( CastExpr *castExpr ) {
-		if ( castExpr->result->isVoid() ) {
-			// can't specialize if we don't have a return value
-			return castExpr;
-		}
-		Expression *specialized = doSpecialization( castExpr->result, castExpr->arg, &castExpr->inferParams );
-		if ( specialized != castExpr->arg ) {
-			// assume here that the specialization incorporates the cast
-			return specialized;
-		} else {
-			return castExpr;
-		}
-	}
-
-	void convertSpecializations( std::list< Declaration* >& translationUnit ) {
-		PassVisitor<Specialize> spec;
-		mutateAll( translationUnit, spec );
-	}
-} // namespace GenPoly
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/GenPoly/SpecializeNew.cpp
===================================================================
--- src/GenPoly/SpecializeNew.cpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/GenPoly/SpecializeNew.cpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -23,5 +23,4 @@
 #include "GenPoly/GenPoly.h"             // for getFunctionType
 #include "ResolvExpr/FindOpenVars.h"     // for findOpenVars
-#include "ResolvExpr/TypeEnvironment.h"  // for FirstOpen, FirstClosed
 
 namespace GenPoly {
Index: src/GenPoly/module.mk
===================================================================
--- src/GenPoly/module.mk	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/GenPoly/module.mk	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -23,5 +23,4 @@
 SRC += $(SRC_GENPOLY) \
 	GenPoly/BoxNew.cpp \
-	GenPoly/Box.cc \
 	GenPoly/Box.h \
 	GenPoly/ErasableScopedMap.h \
@@ -29,12 +28,9 @@
 	GenPoly/FindFunction.h \
 	GenPoly/InstantiateGenericNew.cpp \
-	GenPoly/InstantiateGeneric.cc \
 	GenPoly/InstantiateGeneric.h \
 	GenPoly/LvalueNew.cpp \
-	GenPoly/Lvalue.cc \
 	GenPoly/ScopedSet.h \
 	GenPoly/ScrubTyVars.cc \
 	GenPoly/ScrubTyVars.h \
-	GenPoly/Specialize.cc \
 	GenPoly/SpecializeNew.cpp \
 	GenPoly/Specialize.h
Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/InitTweak/FixGlobalInit.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -20,41 +20,12 @@
 #include <algorithm>               // for replace_if
 
-#include "Common/PassVisitor.h"
-#include "Common/UniqueName.h"     // for UniqueName
-#include "InitTweak.h"             // for isIntrinsicSingleArgCallStmt
-#include "SynTree/LinkageSpec.h"   // for C
-#include "SynTree/Attribute.h"     // for Attribute
-#include "SynTree/Constant.h"      // for Constant
-#include "SynTree/Declaration.h"   // for FunctionDecl, ObjectDecl, Declaration
-#include "SynTree/Expression.h"    // for ConstantExpr, Expression (ptr only)
-#include "SynTree/Initializer.h"   // for ConstructorInit, Initializer
-#include "SynTree/Label.h"         // for Label
-#include "SynTree/Statement.h"     // for CompoundStmt, Statement (ptr only)
-#include "SynTree/Type.h"          // for Type, Type::StorageClasses, Functi...
-#include "SynTree/Visitor.h"       // for acceptAll, Visitor
-
 #include "AST/Expr.hpp"
 #include "AST/Node.hpp"
 #include "AST/Pass.hpp"
+#include "Common/UniqueName.h"     // for UniqueName
+#include "InitTweak.h"             // for isIntrinsicSingleArgCallStmt
 
 namespace InitTweak {
-	class GlobalFixer : public WithShortCircuiting {
-	  public:
-		GlobalFixer( bool inLibrary );
-
-		void previsit( ObjectDecl *objDecl );
-		void previsit( FunctionDecl *functionDecl );
-		void previsit( StructDecl *aggregateDecl );
-		void previsit( UnionDecl *aggregateDecl );
-		void previsit( EnumDecl *aggregateDecl );
-		void previsit( TraitDecl *aggregateDecl );
-		void previsit( TypeDecl *typeDecl );
-
-		UniqueName tempNamer;
-		FunctionDecl * initFunction;
-		FunctionDecl * destroyFunction;
-	};
-
-	class GlobalFixer_new : public ast::WithShortCircuiting {
+	class GlobalFixer : public ast::WithShortCircuiting {
 	public:
 		void previsit (const ast::ObjectDecl *);
@@ -70,45 +41,6 @@
 	};
 
-	void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary ) {
-		PassVisitor<GlobalFixer> visitor( inLibrary );
-		acceptAll( translationUnit, visitor );
-		GlobalFixer & fixer = visitor.pass;
-		// don't need to include function if it's empty
-		if ( fixer.initFunction->get_statements()->get_kids().empty() ) {
-			delete fixer.initFunction;
-		} else {
-			translationUnit.push_back( fixer.initFunction );
-		} // if
-
-		if ( fixer.destroyFunction->get_statements()->get_kids().empty() ) {
-			delete fixer.destroyFunction;
-		} else {
-			translationUnit.push_back( fixer.destroyFunction );
-		} // if
-	}
-
-	GlobalFixer::GlobalFixer( bool inLibrary ) : tempNamer( "_global_init" ) {
-		std::list< Expression * > ctorParameters;
-		std::list< Expression * > dtorParameters;
-		if ( inLibrary ) {
-			// Constructor/destructor attributes take a single parameter which
-			// is the priority, with lower numbers meaning higher priority.
-			// Functions specified with priority are guaranteed to run before
-			// functions without a priority. To ensure that constructors and destructors
-			// for library code are run before constructors and destructors for user code,
-			// specify a priority when building the library. Priorities 0-100 are reserved by gcc.
-			// Priorities 101-200 are reserved by cfa, so use priority 200 for CFA library globals,
-			// allowing room for overriding with a higher priority.
-			ctorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) );
-			dtorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) );
-		}
-		initFunction = new FunctionDecl( "__global_init__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
-		initFunction->get_attributes().push_back( new Attribute( "constructor", ctorParameters ) );
-		destroyFunction = new FunctionDecl( "__global_destroy__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
-		destroyFunction->get_attributes().push_back( new Attribute( "destructor", dtorParameters ) );
-	}
-
 	void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) {
-		ast::Pass<GlobalFixer_new> fixer;
+		ast::Pass<GlobalFixer> fixer;
 		accept_all(translationUnit, fixer);
 
@@ -141,41 +73,5 @@
 	}
 
-	void GlobalFixer::previsit( ObjectDecl *objDecl ) {
-		std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids();
-		std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
-
-		// C allows you to initialize objects with constant expressions
-		// xxx - this is an optimization. Need to first resolve constructors before we decide
-		// to keep C-style initializer.
-		// if ( isConstExpr( objDecl->get_init() ) ) return;
-
-		if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
-			// a decision should have been made by the resolver, so ctor and init are not both non-NULL
-			assert( ! ctorInit->ctor || ! ctorInit->init );
-
-			Statement * dtor = ctorInit->dtor;
-			if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
-				// don't need to call intrinsic dtor, because it does nothing, but
-				// non-intrinsic dtors must be called
-				destroyStatements.push_front( dtor );
-				ctorInit->dtor = nullptr;
-			} // if
-			if ( Statement * ctor = ctorInit->ctor ) {
-				addDataSectionAttribute( objDecl );
-				initStatements.push_back( ctor );
-				objDecl->init = nullptr;
-				ctorInit->ctor = nullptr;
-			} else if ( Initializer * init = ctorInit->init ) {
-				objDecl->init = init;
-				ctorInit->init = nullptr;
-			} else {
-				// no constructor and no initializer, which is okay
-				objDecl->init = nullptr;
-			} // if
-			delete ctorInit;
-		} // if
-	}
-
-	void GlobalFixer_new::previsit(const ast::ObjectDecl * objDecl) {
+	void GlobalFixer::previsit(const ast::ObjectDecl * objDecl) {
 		auto mutDecl = mutate(objDecl);
 		assertf(mutDecl == objDecl, "Global object decl must be unique");
@@ -207,12 +103,4 @@
 	}
 
-	// only modify global variables
-	void GlobalFixer::previsit( FunctionDecl * ) { visit_children = false; }
-	void GlobalFixer::previsit( StructDecl * ) { visit_children = false; }
-	void GlobalFixer::previsit( UnionDecl * ) { visit_children = false; }
-	void GlobalFixer::previsit( EnumDecl * ) { visit_children = false; }
-	void GlobalFixer::previsit( TraitDecl * ) { visit_children = false; }
-	void GlobalFixer::previsit( TypeDecl * ) { visit_children = false; }
-
 } // namespace InitTweak
 
Index: c/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,1291 +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.
-//
-// FixInit.cc --
-//
-// Author           : Rob Schluntz
-// Created On       : Wed Jan 13 16:29:30 2016
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Feb 16 04:17:07 2020
-// Update Count     : 82
-//
-#include "FixInit.h"
-
-#include <stddef.h>                    // for NULL
-#include <algorithm>                   // for set_difference, copy_if
-#include <cassert>                     // for assert, strict_dynamic_cast
-#include <iostream>                    // for operator<<, ostream, basic_ost...
-#include <iterator>                    // for insert_iterator, back_inserter
-#include <list>                        // for _List_iterator, list, list<>::...
-#include <map>                         // for _Rb_tree_iterator, _Rb_tree_co...
-#include <memory>                      // for allocator_traits<>::value_type
-#include <set>                         // for set, set<>::value_type
-#include <unordered_map>               // for unordered_map, unordered_map<>...
-#include <unordered_set>               // for unordered_set
-#include <utility>                     // for pair
-
-#include "CodeGen/GenType.h"           // for genPrettyType
-#include "CodeGen/OperatorTable.h"
-#include "Common/PassVisitor.h"        // for PassVisitor, WithStmtsToAdd
-#include "Common/SemanticError.h"      // for SemanticError
-#include "Common/ToString.hpp"         // for toCString
-#include "Common/UniqueName.h"         // for UniqueName
-#include "FixGlobalInit.h"             // for fixGlobalInit
-#include "GenInit.h"                   // for genCtorDtor
-#include "GenPoly/GenPoly.h"           // for getFunctionType
-#include "InitTweak.h"                 // for getFunctionName, getCallArg
-#include "ResolvExpr/Resolver.h"       // for findVoidExpression
-#include "ResolvExpr/Unify.h"          // for typesCompatible
-#include "SymTab/Autogen.h"            // for genImplicitCall
-#include "SymTab/Indexer.h"            // for Indexer
-#include "SymTab/Mangler.h"            // for Mangler
-#include "SynTree/LinkageSpec.h"       // for C, Spec, Cforall, isBuiltin
-#include "SynTree/Attribute.h"         // for Attribute
-#include "SynTree/Constant.h"          // for Constant
-#include "SynTree/Declaration.h"       // for ObjectDecl, FunctionDecl, Decl...
-#include "SynTree/Expression.h"        // for UniqueExpr, VariableExpr, Unty...
-#include "SynTree/Initializer.h"       // for ConstructorInit, SingleInit
-#include "SynTree/Label.h"             // for Label, operator<
-#include "SynTree/Mutator.h"           // for mutateAll, Mutator, maybeMutate
-#include "SynTree/Statement.h"         // for ExprStmt, CompoundStmt, Branch...
-#include "SynTree/Type.h"              // for Type, Type::StorageClasses
-#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
-#include "SynTree/DeclReplacer.h"      // for DeclReplacer
-#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
-#include "Validate/FindSpecialDecls.h" // for dtorStmt, dtorStructDestroy
-
-extern bool ctordtorp; // print all debug
-extern bool ctorp; // print ctor debug
-extern bool cpctorp; // print copy ctor debug
-extern bool dtorp; // print dtor debug
-#define PRINT( text ) if ( ctordtorp ) { text }
-#define CP_CTOR_PRINT( text ) if ( ctordtorp || cpctorp ) { text }
-#define DTOR_PRINT( text ) if ( ctordtorp || dtorp ) { text }
-
-namespace InitTweak {
-	namespace {
-		struct SelfAssignChecker {
-			void previsit( ApplicationExpr * appExpr );
-		};
-
-		struct StmtExprResult {
-			static void link( std::list< Declaration * > & translationUnit );
-
-			void previsit( StmtExpr * stmtExpr );
-		};
-
-		struct InsertImplicitCalls : public WithConstTypeSubstitution {
-			/// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
-			/// function calls need their parameters to be copy constructed
-			static void insert( std::list< Declaration * > & translationUnit );
-
-			Expression * postmutate( ApplicationExpr * appExpr );
-		};
-
-		struct ResolveCopyCtors final : public WithStmtsToAdd, public WithIndexer, public WithShortCircuiting, public WithTypeSubstitution, public WithVisitorRef<ResolveCopyCtors> {
-			/// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr,
-			/// generate/resolve copy construction expressions for each, and generate/resolve destructors for both
-			/// arguments and return value temporaries
-			static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
-
-			Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
-			void premutate( StmtExpr * stmtExpr );
-			void premutate( UniqueExpr * unqExpr );
-
-			/// create and resolve ctor/dtor expression: fname(var, [cpArg])
-			Expression * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
-			/// true if type does not need to be copy constructed to ensure correctness
-			bool skipCopyConstruct( Type * type );
-			void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal );
-			void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr, Expression *& arg );
-		};
-
-		/// collects constructed object decls - used as a base class
-		struct ObjDeclCollector : public WithGuards, public WithShortCircuiting {
-			// use ordered data structure to maintain ordering for set_difference and for consistent error messages
-			typedef std::list< ObjectDecl * > ObjectSet;
-			void previsit( CompoundStmt *compoundStmt );
-			void previsit( DeclStmt *stmt );
-
-			// don't go into other functions
-			void previsit( FunctionDecl * ) { visit_children = false; }
-
-		  protected:
-			ObjectSet curVars;
-		};
-
-		// debug
-		template<typename ObjectSet>
-		struct PrintSet {
-			PrintSet( const ObjectSet & objs ) : objs( objs ) {}
-			const ObjectSet & objs;
-		};
-		template<typename ObjectSet>
-		PrintSet<ObjectSet> printSet( const ObjectSet & objs ) { return PrintSet<ObjectSet>( objs ); }
-		template<typename ObjectSet>
-		std::ostream & operator<<( std::ostream & out, const PrintSet<ObjectSet> & set) {
-			out << "{ ";
-			for ( ObjectDecl * obj : set.objs ) {
-				out << obj->get_name() << ", " ;
-			} // for
-			out << " }";
-			return out;
-		}
-
-		struct LabelFinder final : public ObjDeclCollector {
-			typedef std::map< Label, ObjectSet > LabelMap;
-			// map of Label -> live variables at that label
-			LabelMap vars;
-
-			typedef ObjDeclCollector Parent;
-			using Parent::previsit;
-			void previsit( Statement * stmt );
-
-			void previsit( CompoundStmt *compoundStmt );
-			void previsit( DeclStmt *stmt );
-		};
-
-		struct InsertDtors final : public ObjDeclCollector, public WithStmtsToAdd {
-			/// insert destructor calls at the appropriate places.  must happen before CtorInit nodes are removed
-			/// (currently by FixInit)
-			static void insert( std::list< Declaration * > & translationUnit );
-
-			typedef std::list< ObjectDecl * > OrderedDecls;
-			typedef std::list< OrderedDecls > OrderedDeclsStack;
-
-			InsertDtors( PassVisitor<LabelFinder> & finder ) : finder( finder ), labelVars( finder.pass.vars ) {}
-
-			typedef ObjDeclCollector Parent;
-			using Parent::previsit;
-
-			void previsit( FunctionDecl * funcDecl );
-
-			void previsit( BranchStmt * stmt );
-		private:
-			void handleGoto( BranchStmt * stmt );
-
-			PassVisitor<LabelFinder> & finder;
-			LabelFinder::LabelMap & labelVars;
-			OrderedDeclsStack reverseDeclOrder;
-		};
-
-		class FixInit : public WithStmtsToAdd {
-		  public:
-			/// expand each object declaration to use its constructor after it is declared.
-			static void fixInitializers( std::list< Declaration * > &translationUnit );
-
-			DeclarationWithType * postmutate( ObjectDecl *objDecl );
-
-			std::list< Declaration * > staticDtorDecls;
-		};
-
-		struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer, public WithVisitorRef<GenStructMemberCalls> {
-			/// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors
-			/// for any member that is missing a corresponding ctor/dtor call.
-			/// error if a member is used before constructed
-			static void generate( std::list< Declaration * > & translationUnit );
-
-			void premutate( FunctionDecl * funcDecl );
-			DeclarationWithType * postmutate( FunctionDecl * funcDecl );
-
-			void premutate( MemberExpr * memberExpr );
-			void premutate( ApplicationExpr * appExpr );
-
-			/// Note: this post mutate used to be in a separate visitor. If this pass breaks, one place to examine is whether it is
-			/// okay for this part of the recursion to occur alongside the rest.
-			Expression * postmutate( UntypedExpr * expr );
-
-			SemanticErrorException errors;
-		  private:
-			template< typename... Params >
-			void emit( CodeLocation, const Params &... params );
-
-			FunctionDecl * function = nullptr;
-			std::set< DeclarationWithType * > unhandled;
-			std::map< DeclarationWithType *, CodeLocation > usedUninit;
-			ObjectDecl * thisParam = nullptr;
-			bool isCtor = false; // true if current function is a constructor
-			StructDecl * structDecl = nullptr;
-		};
-
-		struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer {
-			/// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
-			static void fix( std::list< Declaration * > & translationUnit );
-
-			Expression * postmutate( ConstructorExpr * ctorExpr );
-		};
-
-		struct SplitExpressions : public WithShortCircuiting, /*public WithTypeSubstitution, */public WithStmtsToAdd {
-			/// add CompoundStmts around top-level expressions so that temporaries are destroyed in the correct places.
-			static void split( std::list< Declaration * > &translationUnit );
-
-			Statement * postmutate( ExprStmt * stmt );
-			void premutate( TupleAssignExpr * expr );
-		};
-	} // namespace
-
-	void fix( std::list< Declaration * > & translationUnit, bool inLibrary ) {
-		PassVisitor<SelfAssignChecker> checker;
-		acceptAll( translationUnit, checker );
-
-		// fixes StmtExpr to properly link to their resulting expression
-		StmtExprResult::link( translationUnit );
-
-		// fixes ConstructorInit for global variables. should happen before fixInitializers.
-		InitTweak::fixGlobalInit( translationUnit, inLibrary );
-
-		// must happen before ResolveCopyCtors because temporaries have to be inserted into the correct scope
-		SplitExpressions::split( translationUnit );
-
-		InsertImplicitCalls::insert( translationUnit );
-
-		// Needs to happen before ResolveCopyCtors, because argument/return temporaries should not be considered in
-		// error checking branch statements
-		InsertDtors::insert( translationUnit );
-
-		ResolveCopyCtors::resolveImplicitCalls( translationUnit );
-		FixInit::fixInitializers( translationUnit );
-		GenStructMemberCalls::generate( translationUnit );
-
-		// Needs to happen after GenStructMemberCalls, since otherwise member constructors exprs
-		// don't have the correct form, and a member can be constructed more than once.
-		FixCtorExprs::fix( translationUnit );
-	}
-
-	namespace {
-		/// find and return the destructor used in `input`. If `input` is not a simple destructor call, generate a thunk
-		/// that wraps the destructor, insert it into `stmtsToAdd` and return the new function declaration
-		DeclarationWithType * getDtorFunc( ObjectDecl * objDecl, Statement * input, std::list< Statement * > & stmtsToAdd ) {
-			// unwrap implicit statement wrapper
-			Statement * dtor = input;
-			assert( dtor );
-			std::list< Expression * > matches;
-			collectCtorDtorCalls( dtor, matches );
-
-			if ( dynamic_cast< ExprStmt * >( dtor ) ) {
-				// only one destructor call in the expression
-				if ( matches.size() == 1 ) {
-					DeclarationWithType * func = getFunction( matches.front() );
-					assertf( func, "getFunction failed to find function in %s", toString( matches.front() ).c_str() );
-
-					// cleanup argument must be a function, not an object (including function pointer)
-					if ( FunctionDecl * dtorFunc = dynamic_cast< FunctionDecl * > ( func ) ) {
-						if ( dtorFunc->type->forall.empty() ) {
-							// simple case where the destructor is a monomorphic function call - can simply
-							// use that function as the cleanup function.
-							delete dtor;
-							return func;
-						}
-					}
-				}
-			}
-
-			// otherwise the cleanup is more complicated - need to build a single argument cleanup function that
-			// wraps the more complicated code.
-			static UniqueName dtorNamer( "__cleanup_dtor" );
-			std::string name = dtorNamer.newName();
-			FunctionDecl * dtorFunc = FunctionDecl::newFunction( name, SymTab::genDefaultType( objDecl->type->stripReferences(), false ), new CompoundStmt() );
-			stmtsToAdd.push_back( new DeclStmt( dtorFunc ) );
-
-			// the original code contains uses of objDecl - replace them with the newly generated 'this' parameter.
-			ObjectDecl * thisParam = getParamThis( dtorFunc->type );
-			Expression * replacement = new VariableExpr( thisParam );
-
-			Type * base = replacement->result->stripReferences();
-			if ( dynamic_cast< ArrayType * >( base ) || dynamic_cast< TupleType * > ( base ) ) {
-				// need to cast away reference for array types, since the destructor is generated without the reference type,
-				// and for tuple types since tuple indexing does not work directly on a reference
-				replacement = new CastExpr( replacement, base->clone() );
-			}
-			DeclReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } );
-			dtorFunc->statements->push_back( strict_dynamic_cast<Statement *>( dtor ) );
-
-			return dtorFunc;
-		}
-
-		void StmtExprResult::link( std::list< Declaration * > & translationUnit ) {
-			PassVisitor<StmtExprResult> linker;
-			acceptAll( translationUnit, linker );
-		}
-
-		void SplitExpressions::split( std::list< Declaration * > & translationUnit ) {
-			PassVisitor<SplitExpressions> splitter;
-			mutateAll( translationUnit, splitter );
-		}
-
-		void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit ) {
-			PassVisitor<InsertImplicitCalls> inserter;
-			mutateAll( translationUnit, inserter );
-		}
-
-		void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit ) {
-			PassVisitor<ResolveCopyCtors> resolver;
-			mutateAll( translationUnit, resolver );
-		}
-
-		void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
-			PassVisitor<FixInit> fixer;
-
-			// can't use mutateAll, because need to insert declarations at top-level
-			// can't use DeclMutator, because sometimes need to insert IfStmt, etc.
-			SemanticErrorException errors;
-			for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
-				try {
-					maybeMutate( *i, fixer );
-					translationUnit.splice( i, fixer.pass.staticDtorDecls );
-				} catch( SemanticErrorException &e ) {
-					errors.append( e );
-				} // try
-			} // for
-			if ( ! errors.isEmpty() ) {
-				throw errors;
-			} // if
-		}
-
-		void InsertDtors::insert( std::list< Declaration * > & translationUnit ) {
-			PassVisitor<LabelFinder> finder;
-			PassVisitor<InsertDtors> inserter( finder );
-			acceptAll( translationUnit, inserter );
-		}
-
-		void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
-			PassVisitor<GenStructMemberCalls> warner;
-			mutateAll( translationUnit, warner );
-		}
-
-		void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) {
-			PassVisitor<FixCtorExprs> fixer;
-			mutateAll( translationUnit, fixer );
-		}
-
-		void StmtExprResult::previsit( StmtExpr * stmtExpr ) {
-			// we might loose the result expression here so add a pointer to trace back
-			assert( stmtExpr->result );
-			Type * result = stmtExpr->result;
-			if ( ! result->isVoid() ) {
-				CompoundStmt * body = stmtExpr->statements;
-				assert( ! body->kids.empty() );
-				stmtExpr->resultExpr = strict_dynamic_cast< ExprStmt * >( body->kids.back() );
-			}
-		}
-
-		Statement * SplitExpressions::postmutate( ExprStmt * stmt ) {
-			// wrap each top-level ExprStmt in a block so that destructors for argument and return temporaries are destroyed
-			// in the correct places
-			CompoundStmt * ret = new CompoundStmt( { stmt } );
-			return ret;
-		}
-
-		void SplitExpressions::premutate( TupleAssignExpr * ) {
-			// don't do this within TupleAssignExpr, since it is already broken up into multiple expressions
-			visit_children = false;
-		}
-
-		// Relatively simple structural comparison for expressions, needed to determine
-		// if two expressions are "the same" (used to determine if self assignment occurs)
-		struct StructuralChecker {
-			Expression * stripCasts( Expression * expr ) {
-				// this might be too permissive. It's possible that only particular casts are relevant.
-				while ( CastExpr * cast = dynamic_cast< CastExpr * >( expr ) ) {
-					expr = cast->arg;
-				}
-				return expr;
-			}
-
-			void previsit( Expression * ) {
-				// anything else does not qualify
-				isSimilar = false;
-			}
-
-			template<typename T>
-			T * cast( Expression * node ) {
-				// all expressions need to ignore casts, so this bit has been factored out
-				return dynamic_cast< T * >( stripCasts( node ) );
-			}
-
-			// ignore casts
-			void previsit( CastExpr * ) {}
-
-			void previsit( MemberExpr * memExpr ) {
-				if ( MemberExpr * otherMember = cast< MemberExpr >( other ) ) {
-					if ( otherMember->member == memExpr->member ) {
-						other = otherMember->aggregate;
-						return;
-					}
-				}
-				isSimilar = false;
-			}
-
-			void previsit( VariableExpr * varExpr ) {
-				if ( VariableExpr * otherVar = cast< VariableExpr >( other ) ) {
-					if ( otherVar->var == varExpr->var ) {
-						return;
-					}
-				}
-				isSimilar = false;
-			}
-
-			void previsit( AddressExpr * ) {
-				if ( AddressExpr * addrExpr = cast< AddressExpr >( other ) ) {
-					other = addrExpr->arg;
-					return;
-				}
-				isSimilar = false;
-			}
-
-			Expression * other = nullptr;
-			bool isSimilar = true;
-		};
-
-		bool structurallySimilar( Expression * e1, Expression * e2 ) {
-			PassVisitor<StructuralChecker> checker;
-			checker.pass.other = e2;
-			e1->accept( checker );
-			return checker.pass.isSimilar;
-		}
-
-		void SelfAssignChecker::previsit( ApplicationExpr * appExpr ) {
-			DeclarationWithType * function = getFunction( appExpr );
-			if ( function->name == "?=?" ) { // doesn't use isAssignment, because ?+=?, etc. should not count as self-assignment
-				if ( appExpr->args.size() == 2 ) {
-					// check for structural similarity (same variable use, ignore casts, etc. - but does not look too deeply, anything looking like a function is off limits)
-					if ( structurallySimilar( appExpr->args.front(), appExpr->args.back() ) ) {
-						SemanticWarning( appExpr->location, Warning::SelfAssignment, toCString( appExpr->args.front() ) );
-					}
-				}
-			}
-		}
-
-		Expression * InsertImplicitCalls::postmutate( ApplicationExpr * appExpr ) {
-			if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) {
-				if ( function->var->linkage.is_builtin ) {
-					// optimization: don't need to copy construct in order to call intrinsic functions
-					return appExpr;
-				} else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) {
-					FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
-					assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() );
-					if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->parameters.size() == 2 ) {
-						Type * t1 = getPointerBase( ftype->parameters.front()->get_type() );
-						Type * t2 = ftype->parameters.back()->get_type();
-						assert( t1 );
-
-						if ( ResolvExpr::typesCompatible( t1, t2, SymTab::Indexer() ) ) {
-							// optimization: don't need to copy construct in order to call a copy constructor
-							return appExpr;
-						} // if
-					} else if ( CodeGen::isDestructor( funcDecl->get_name() ) ) {
-						// correctness: never copy construct arguments to a destructor
-						return appExpr;
-					} // if
-				} // if
-			} // if
-			CP_CTOR_PRINT( std::cerr << "InsertImplicitCalls: adding a wrapper " << appExpr << std::endl; )
-
-			// wrap each function call so that it is easy to identify nodes that have to be copy constructed
-			ImplicitCopyCtorExpr * expr = new ImplicitCopyCtorExpr( appExpr );
-			// Move the type substitution to the new top-level, if it is attached to the appExpr.
-			// Ensure it is not deleted with the ImplicitCopyCtorExpr by removing it before deletion.
-			// The substitution is needed to obtain the type of temporary variables so that copy constructor
-			// calls can be resolved.
-			assert( env );
-			std::swap( expr->env, appExpr->env );
-			return expr;
-		}
-
-		bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); }
-
-		Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
-			assert( var );
-			// arrays are not copy constructed, so this should always be an ExprStmt
-			ImplicitCtorDtorStmt * stmt = genCtorDtor( fname, var, cpArg );
-			assertf( stmt, "ResolveCopyCtors: genCtorDtor returned nullptr: %s / %s / %s", fname.c_str(), toString( var ).c_str(), toString( cpArg ).c_str() );
-			ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->callStmt );
-			Expression * resolved = exprStmt->expr;
-			exprStmt->expr = nullptr; // take ownership of expr
-
-			// resolve copy constructor
-			// should only be one alternative for copy ctor and dtor expressions, since all arguments are fixed
-			// (VariableExpr and already resolved expression)
-			CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << resolved << std::endl; )
-			ResolvExpr::findVoidExpression( resolved, indexer );
-			assert( resolved );
-			if ( resolved->env ) {
-				// Extract useful information and discard new environments. Keeping them causes problems in PolyMutator passes.
-				env->add( *resolved->env );
-				delete resolved->env;
-				resolved->env = nullptr;
-			} // if
-			delete stmt;
-			if ( TupleAssignExpr * assign = dynamic_cast< TupleAssignExpr * >( resolved ) ) {
-				// fix newly generated StmtExpr
-				premutate( assign->stmtExpr );
-			}
-			return resolved;
-		}
-
-		void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal ) {
-			static UniqueName tempNamer("_tmp_cp");
-			assert( env );
-			CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; )
-			assert( arg->result );
-			Type * result = arg->result;
-			if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types
-
-			// type may involve type variables, so apply type substitution to get temporary variable's actual type,
-			// since result type may not be substituted (e.g., if the type does not appear in the parameter list)
-			// Use applyFree so that types bound in function pointers are not substituted, e.g. in forall(dtype T) void (*)(T).
-			env->applyFree( result );
-			ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr );
-			tmp->get_type()->set_const( false );
-
-			// create and resolve copy constructor
-			CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; )
-			Expression * cpCtor = makeCtorDtor( "?{}", tmp, arg );
-
-			if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( cpCtor ) ) {
-				// if the chosen constructor is intrinsic, the copy is unnecessary, so
-				// don't create the temporary and don't call the copy constructor
-				VariableExpr * function = strict_dynamic_cast< VariableExpr * >( appExpr->function );
-				if ( function->var->linkage == LinkageSpec::Intrinsic ) {
-					// arguments that need to be boxed need a temporary regardless of whether the copy constructor is intrinsic,
-					// so that the object isn't changed inside of the polymorphic function
-					if ( ! GenPoly::needsBoxing( formal, result, impCpCtorExpr->callExpr, env ) ) return;
-					// xxx - leaking tmp
-				}
-			}
-
-			// set a unique name for the temporary once it's certain the call is necessary
-			tmp->name = tempNamer.newName();
-
-			// replace argument to function call with temporary
-			stmtsToAddBefore.push_back( new DeclStmt( tmp ) );
-			arg = cpCtor;
-			destructRet( tmp, impCpCtorExpr, arg );
-
-			// impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) );
-		}
-
-		void ResolveCopyCtors::destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * /*impCpCtorExpr*/, Expression *& arg ) {
-			// TODO: refactor code for generating cleanup attribute, since it's common and reused in ~3-4 places
-			// check for existing cleanup attribute before adding another(?)
-			// need to add __Destructor for _tmp_cp variables as well
-
-			assertf( Validate::dtorStruct && Validate::dtorStruct->members.size() == 2, "Destructor generation requires __Destructor definition." );
-			assertf( Validate::dtorStructDestroy, "Destructor generation requires __destroy_Destructor." );
-
-			// generate a __Destructor for ret that calls the destructor
-			Expression * dtor = makeCtorDtor( "^?{}", ret );
-
-			// if the chosen destructor is intrinsic, elide the generated dtor handler
-			if ( arg && isIntrinsicCallExpr( dtor ) ) {
-				arg = new CommaExpr( arg, new VariableExpr( ret ) );
-				return;
-			}
-
-			if ( ! dtor->env ) dtor->env = maybeClone( env );
-			DeclarationWithType * dtorFunc = getDtorFunc( ret, new ExprStmt( dtor ), stmtsToAddBefore );
-
-			StructInstType * dtorStructType = new StructInstType( Type::Qualifiers(), Validate::dtorStruct );
-			dtorStructType->parameters.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
-
-			// cast destructor pointer to void (*)(void *), to silence GCC incompatible pointer warnings
-			FunctionType * dtorFtype = new FunctionType( Type::Qualifiers(), false );
-			dtorFtype->parameters.push_back( ObjectDecl::newObject( "", new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), nullptr ) );
-			Type * dtorType = new PointerType( Type::Qualifiers(), dtorFtype );
-
-			static UniqueName namer( "_ret_dtor" );
-			ObjectDecl * retDtor = ObjectDecl::newObject( namer.newName(), dtorStructType, new ListInit( { new SingleInit( new ConstantExpr( Constant::null() ) ), new SingleInit( new CastExpr( new VariableExpr( dtorFunc ), dtorType ) ) } ) );
-			retDtor->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( Validate::dtorStructDestroy ) } ) );
-			stmtsToAddBefore.push_back( new DeclStmt( retDtor ) );
-
-			if ( arg ) {
-				Expression * member = new MemberExpr( strict_dynamic_cast<DeclarationWithType *>( Validate::dtorStruct->members.front() ), new VariableExpr( retDtor ) );
-				Expression * object = new CastExpr( new AddressExpr( new VariableExpr( ret ) ), new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ) );
-				Expression * assign = createBitwiseAssignment( member, object );
-				arg = new CommaExpr( new CommaExpr( arg, assign ), new VariableExpr( ret ) );
-			}
-
-			// impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
-		}
-
-		Expression * ResolveCopyCtors::postmutate( ImplicitCopyCtorExpr *impCpCtorExpr ) {
-			CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
-
-			ApplicationExpr * appExpr = impCpCtorExpr->callExpr;
-			ObjectDecl * returnDecl = nullptr;
-
-			// take each argument and attempt to copy construct it.
-			FunctionType * ftype = GenPoly::getFunctionType( appExpr->function->result );
-			assert( ftype );
-			auto & params = ftype->parameters;
-			auto iter = params.begin();
-			for ( Expression * & arg : appExpr->args ) {
-				Type * formal = nullptr;
-				if ( iter != params.end() ) { // does not copy construct C-style variadic arguments
-					DeclarationWithType * param = *iter++;
-					formal = param->get_type();
-				}
-
-				copyConstructArg( arg, impCpCtorExpr, formal );
-			} // for
-
-			// each return value from the call needs to be connected with an ObjectDecl at the call site, which is
-			// initialized with the return value and is destructed later
-			// xxx - handle named return values?
-			Type * result = appExpr->result;
-			if ( ! result->isVoid() ) {
-				static UniqueName retNamer("_tmp_cp_ret");
-				result = result->clone();
-				env->apply( result );
-				ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
-				ret->type->set_const( false );
-				returnDecl = ret;
-				stmtsToAddBefore.push_back( new DeclStmt( ret ) );
-				CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
-			} // for
-			CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
-			// ------------------------------------------------------
-
-			CP_CTOR_PRINT( std::cerr << "Coming out the back..." << impCpCtorExpr << std::endl; )
-
-			// detach fields from wrapper node so that it can be deleted without deleting too much
-			impCpCtorExpr->callExpr = nullptr;
-			std::swap( impCpCtorExpr->env, appExpr->env );
-			assert( impCpCtorExpr->env == nullptr );
-			delete impCpCtorExpr;
-
-			if ( returnDecl ) {
-				Expression * assign = createBitwiseAssignment( new VariableExpr( returnDecl ), appExpr );
-				if ( ! dynamic_cast< ReferenceType * >( result ) ) {
-					// destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
-					destructRet( returnDecl, impCpCtorExpr, assign );
-				} else {
-					assign = new CommaExpr( assign, new VariableExpr( returnDecl ) );
-				}
-				// move env from appExpr to retExpr
-				std::swap( assign->env, appExpr->env );
-				return assign;
-			} else {
-				return appExpr;
-			} // if
-		}
-
-		void ResolveCopyCtors::premutate( StmtExpr * stmtExpr ) {
-			// function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
-			// since temporaries can be shared across sub-expressions, e.g.
-			//   [A, A] f();       // decl
-			//   g([A] x, [A] y);  // decl
-			//   g(f());           // call
-			// f is executed once, so the return temporary is shared across the tuple constructors for x and y.
-			// Explicitly mutating children instead of mutating the inner compound statement forces the temporaries to be added
-			// to the outer context, rather than inside of the statement expression.
-			visit_children = false;
-
-			assert( env );
-
-			indexer.enterScope();
-			// visit all statements
-			std::list< Statement * > & stmts = stmtExpr->statements->get_kids();
-			for ( Statement *& stmt : stmts ) {
-				stmt = stmt->acceptMutator( *visitor );
-			} // for
-			indexer.leaveScope();
-
-			assert( stmtExpr->result );
-			Type * result = stmtExpr->result;
-			if ( ! result->isVoid() ) {
-				static UniqueName retNamer("_tmp_stmtexpr_ret");
-
-				result = result->clone();
-				env->apply( result );
-				if ( ! InitTweak::isConstructable( result ) ) {
-					delete result;
-					return;
-				}
-
-				// create variable that will hold the result of the stmt expr
-				ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
-				ret->type->set_const( false );
-				stmtsToAddBefore.push_back( new DeclStmt( ret ) );
-
-				assertf(
-					stmtExpr->resultExpr,
-					"Statement-Expression should have a resulting expression at %s:%d",
-					stmtExpr->location.filename.c_str(),
-					stmtExpr->location.first_line
-				);
-
-				ExprStmt * last = stmtExpr->resultExpr;
-				try {
-					last->expr = makeCtorDtor( "?{}", ret, last->expr );
-				} catch(...) {
-					std::cerr << "*CFA internal error: ";
-					std::cerr << "can't resolve implicit constructor";
-					std::cerr << " at " << stmtExpr->location.filename;
-					std::cerr << ":" << stmtExpr->location.first_line << std::endl;
-
-					abort();
-				}
-
-				// add destructors after current statement
-				stmtsToAddAfter.push_back( new ExprStmt( makeCtorDtor( "^?{}", ret ) ) );
-
-				// must have a non-empty body, otherwise it wouldn't have a result
-				assert( ! stmts.empty() );
-
-				// if there is a return decl, add a use as the last statement; will not have return decl on non-constructable returns
-				stmts.push_back( new ExprStmt( new VariableExpr( ret ) ) );
-			} // if
-
-			assert( stmtExpr->returnDecls.empty() );
-			assert( stmtExpr->dtors.empty() );
-		}
-
-		// to prevent warnings ('_unq0' may be used uninitialized in this function),
-		// insert an appropriate zero initializer for UniqueExpr temporaries.
-		Initializer * makeInit( Type * t ) {
-			if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) {
-				// initizer for empty struct must be empty
-				if ( inst->baseStruct->members.empty() ) return new ListInit({});
-			} else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {
-				// initizer for empty union must be empty
-				if ( inst->baseUnion->members.empty() ) return new ListInit({});
-			}
-
-			return new ListInit( { new SingleInit( new ConstantExpr( Constant::from_int( 0 ) ) ) } );
-		}
-
-		void ResolveCopyCtors::premutate( UniqueExpr * unqExpr ) {
-			visit_children = false;
-			// xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
-			static std::unordered_map< int, UniqueExpr * > unqMap;
-			if ( ! unqMap.count( unqExpr->get_id() ) ) {
-				// resolve expr and find its
-
-				ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast< ImplicitCopyCtorExpr * >( unqExpr->expr );
-				// PassVisitor<ResolveCopyCtors> fixer;
-				unqExpr->expr = unqExpr->expr->acceptMutator( *visitor );
-
-				// it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought
-				assert( unqExpr->result );
-				if ( impCpCtorExpr ) {
-					CommaExpr * comma = strict_dynamic_cast< CommaExpr * >( unqExpr->expr );
-					VariableExpr * var = strict_dynamic_cast<VariableExpr *>( comma->arg2 );
-					// note the variable used as the result from the call
-					unqExpr->var = var->clone();
-				} else {
-					// expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
-					unqExpr->object = ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->result->clone(), makeInit( unqExpr->result ) );
-					unqExpr->var = new VariableExpr( unqExpr->object );
-				}
-
-				// stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
-				// stmtsToAddAfter.splice( stmtsToAddAfter.end(), fixer.pass.stmtsToAddAfter );
-				unqMap[unqExpr->get_id()] = unqExpr;
-			} else {
-				// take data from other UniqueExpr to ensure consistency
-				delete unqExpr->get_expr();
-				unqExpr->expr = unqMap[unqExpr->get_id()]->expr->clone();
-				delete unqExpr->result;
-				unqExpr->result = maybeClone( unqExpr->expr->result );
-			}
-		}
-
-		DeclarationWithType * FixInit::postmutate( ObjectDecl *objDecl ) {
-			// since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate)
-			if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
-				// a decision should have been made by the resolver, so ctor and init are not both non-NULL
-				assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
-				if ( Statement * ctor = ctorInit->get_ctor() ) {
-					if ( objDecl->get_storageClasses().is_static ) {
-
-						// The ojbect needs to go in the data section, regardless of dtor complexity below.
-						// The attribute works, and is meant to apply, both for leaving the static local alone,
-						// and for hoisting it out as a static global.
-						addDataSectionAttribute( objDecl );
-
-						// originally wanted to take advantage of gcc nested functions, but
-						// we get memory errors with this approach. To remedy this, the static
-						// variable is hoisted when the destructor needs to be called.
-						//
-						// generate:
-						// static T __objName_static_varN;
-						// void __objName_dtor_atexitN() {
-						//   __dtor__...;
-						// }
-						// int f(...) {
-						//   ...
-						//   static bool __objName_uninitialized = true;
-						//   if (__objName_uninitialized) {
-						//     __ctor(__objName);
-						//     __objName_uninitialized = false;
-						//     atexit(__objName_dtor_atexitN);
-						//   }
-						//   ...
-						// }
-
-						static UniqueName dtorCallerNamer( "_dtor_atexit" );
-
-						// static bool __objName_uninitialized = true
-						BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
-						SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant::from_int( 1 ) ) );
-						ObjectDecl * isUninitializedVar = new ObjectDecl( objDecl->get_mangleName() + "_uninitialized", Type::StorageClasses( Type::Static ), LinkageSpec::Cforall, 0, boolType, boolInitExpr );
-						isUninitializedVar->fixUniqueId();
-
-						// __objName_uninitialized = false;
-						UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) );
-						setTrue->get_args().push_back( new VariableExpr( isUninitializedVar ) );
-						setTrue->get_args().push_back( new ConstantExpr( Constant::from_int( 0 ) ) );
-
-						// generate body of if
-						CompoundStmt * initStmts = new CompoundStmt();
-						std::list< Statement * > & body = initStmts->get_kids();
-						body.push_back( ctor );
-						body.push_back( new ExprStmt( setTrue ) );
-
-						// put it all together
-						IfStmt * ifStmt = new IfStmt( new VariableExpr( isUninitializedVar ), initStmts, 0 );
-						stmtsToAddAfter.push_back( new DeclStmt( isUninitializedVar ) );
-						stmtsToAddAfter.push_back( ifStmt );
-
-						Statement * dtor = ctorInit->get_dtor();
-						objDecl->set_init( nullptr );
-						ctorInit->set_ctor( nullptr );
-						ctorInit->set_dtor( nullptr );
-						if ( dtor ) {
-							// if the object has a non-trivial destructor, have to
-							// hoist it and the object into the global space and
-							// call the destructor function with atexit.
-
-							Statement * dtorStmt = dtor->clone();
-
-							// void __objName_dtor_atexitN(...) {...}
-							FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
-							dtorCaller->fixUniqueId();
-							dtorCaller->get_statements()->push_back( dtorStmt );
-
-							// atexit(dtor_atexit);
-							UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
-							callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
-
-							body.push_back( new ExprStmt( callAtexit ) );
-
-							// hoist variable and dtor caller decls to list of decls that will be added into global scope
-							staticDtorDecls.push_back( objDecl );
-							staticDtorDecls.push_back( dtorCaller );
-
-							// need to rename object uniquely since it now appears
-							// at global scope and there could be multiple function-scoped
-							// static variables with the same name in different functions.
-							// Note: it isn't sufficient to modify only the mangleName, because
-							// then subsequent Indexer passes can choke on seeing the object's name
-							// if another object has the same name and type. An unfortunate side-effect
-							// of renaming the object is that subsequent NameExprs may fail to resolve,
-							// but there shouldn't be any remaining past this point.
-							static UniqueName staticNamer( "_static_var" );
-							objDecl->set_name( objDecl->get_name() + staticNamer.newName() );
-							objDecl->set_mangleName( SymTab::Mangler::mangle( objDecl ) );
-
-							// xxx - temporary hack: need to return a declaration, but want to hoist the current object out of this scope
-							// create a new object which is never used
-							static UniqueName dummyNamer( "_dummy" );
-							ObjectDecl * dummy = new ObjectDecl( dummyNamer.newName(), Type::StorageClasses( Type::Static ), LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), 0, std::list< Attribute * >{ new Attribute("unused") } );
-							delete ctorInit;
-							return dummy;
-						}
-					} else {
-						ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * > ( ctor );
-						ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit->callStmt );
-						ApplicationExpr * ctorCall = nullptr;
-						if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->expr )) && ctorCall->get_args().size() == 2 ) {
-							// clean up intrinsic copy constructor calls by making them into SingleInits
-							Expression * ctorArg = ctorCall->args.back();
-							std::swap( ctorArg->env, ctorCall->env );
-							objDecl->init = new SingleInit( ctorArg );
-
-							ctorCall->args.pop_back();
-						} else {
-							stmtsToAddAfter.push_back( ctor );
-							objDecl->init = nullptr;
-							ctorInit->ctor = nullptr;
-						}
-
-						Statement * dtor = ctorInit->dtor;
-						if ( dtor ) {
-							ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * >( dtor );
-							Statement * dtorStmt = implicit->callStmt;
-
-							// don't need to call intrinsic dtor, because it does nothing, but
-							// non-intrinsic dtors must be called
-							if ( ! isIntrinsicSingleArgCallStmt( dtorStmt ) ) {
-								// set dtor location to the object's location for error messages
-								DeclarationWithType * dtorFunc = getDtorFunc( objDecl, dtorStmt, stmtsToAddBefore );
-								objDecl->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorFunc ) } ) );
-								ctorInit->dtor = nullptr;
-							} // if
-						}
-					} // if
-				} else if ( Initializer * init = ctorInit->init ) {
-					objDecl->init = init;
-					ctorInit->init = nullptr;
-				} else {
-					// no constructor and no initializer, which is okay
-					objDecl->init = nullptr;
-				} // if
-				delete ctorInit;
-			} // if
-			return objDecl;
-		}
-
-		void ObjDeclCollector::previsit( CompoundStmt * ) {
-			GuardValue( curVars );
-		}
-
-		void ObjDeclCollector::previsit( DeclStmt * stmt ) {
-			// keep track of all variables currently in scope
-			if ( ObjectDecl * objDecl = dynamic_cast< ObjectDecl * > ( stmt->get_decl() ) ) {
-				curVars.push_back( objDecl );
-			} // if
-		}
-
-		void LabelFinder::previsit( Statement * stmt ) {
-			// for each label, remember the variables in scope at that label.
-			for ( Label l : stmt->get_labels() ) {
-				vars[l] = curVars;
-			} // for
-		}
-
-		void LabelFinder::previsit( CompoundStmt * stmt ) {
-			previsit( (Statement *)stmt );
-			Parent::previsit( stmt );
-		}
-
-		void LabelFinder::previsit( DeclStmt * stmt ) {
-			previsit( (Statement *)stmt );
-			Parent::previsit( stmt );
-		}
-
-
-		void InsertDtors::previsit( FunctionDecl * funcDecl ) {
-			// each function needs to have its own set of labels
-			GuardValue( labelVars );
-			labelVars.clear();
-			// LabelFinder does not recurse into FunctionDecl, so need to visit
-			// its children manually.
-			maybeAccept( funcDecl->type, finder );
-			maybeAccept( funcDecl->statements, finder );
-
-			// all labels for this function have been collected, insert destructors as appropriate via implicit recursion.
-		}
-
-		// Handle break/continue/goto in the same manner as C++.  Basic idea: any objects that are in scope at the
-		// BranchStmt but not at the labelled (target) statement must be destructed.  If there are any objects in scope
-		// at the target location but not at the BranchStmt then those objects would be uninitialized so notify the user
-		// of the error.  See C++ Reference 6.6 Jump Statements for details.
-		void InsertDtors::handleGoto( BranchStmt * stmt ) {
-			// can't do anything for computed goto
-			if ( stmt->computedTarget ) return;
-
-			assertf( stmt->get_target() != "", "BranchStmt missing a label: %s", toString( stmt ).c_str() );
-			// S_L = lvars = set of objects in scope at label definition
-			// S_G = curVars = set of objects in scope at goto statement
-			ObjectSet & lvars = labelVars[ stmt->get_target() ];
-
-			DTOR_PRINT(
-				std::cerr << "at goto label: " << stmt->get_target().get_name() << std::endl;
-				std::cerr << "S_G = " << printSet( curVars ) << std::endl;
-				std::cerr << "S_L = " << printSet( lvars ) << std::endl;
-			)
-
-
-			// std::set_difference requires that the inputs be sorted.
-			lvars.sort();
-			curVars.sort();
-
-			ObjectSet diff;
-			// S_L-S_G results in set of objects whose construction is skipped - it's an error if this set is non-empty
-			std::set_difference( lvars.begin(), lvars.end(), curVars.begin(), curVars.end(), std::inserter( diff, diff.begin() ) );
-			DTOR_PRINT(
-				std::cerr << "S_L-S_G = " << printSet( diff ) << std::endl;
-			)
-			if ( ! diff.empty() ) {
-				SemanticError( stmt, std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " " );
-			} // if
-		}
-
-		void InsertDtors::previsit( BranchStmt * stmt ) {
-			switch( stmt->get_type() ) {
-			  case BranchStmt::Continue:
-			  case BranchStmt::Break:
-				// could optimize the break/continue case, because the S_L-S_G check is unnecessary (this set should
-				// always be empty), but it serves as a small sanity check.
-			  case BranchStmt::Goto:
-				handleGoto( stmt );
-				break;
-			  default:
-				assert( false );
-			} // switch
-		}
-
-		bool checkWarnings( FunctionDecl * funcDecl ) {
-			// only check for warnings if the current function is a user-defined
-			// constructor or destructor
-			if ( ! funcDecl ) return false;
-			if ( ! funcDecl->get_statements() ) return false;
-			return CodeGen::isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
-		}
-
-		void GenStructMemberCalls::premutate( FunctionDecl * funcDecl ) {
-			GuardValue( function );
-			GuardValue( unhandled );
-			GuardValue( usedUninit );
-			GuardValue( thisParam );
-			GuardValue( isCtor );
-			GuardValue( structDecl );
-			errors = SemanticErrorException();  // clear previous errors
-
-			// need to start with fresh sets
-			unhandled.clear();
-			usedUninit.clear();
-
-			function = funcDecl;
-			isCtor = CodeGen::isConstructor( function->get_name() );
-			if ( checkWarnings( function ) ) {
-				FunctionType * type = function->get_functionType();
-				assert( ! type->get_parameters().empty() );
-				thisParam = strict_dynamic_cast< ObjectDecl * >( type->get_parameters().front() );
-				Type * thisType = getPointerBase( thisParam->get_type() );
-				StructInstType * structType = dynamic_cast< StructInstType * >( thisType );
-				if ( structType ) {
-					structDecl = structType->get_baseStruct();
-					for ( Declaration * member : structDecl->get_members() ) {
-						if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
-							// record all of the struct type's members that need to be constructed or
-							// destructed by the end of the function
-							unhandled.insert( field );
-						}
-					}
-				}
-			}
-		}
-
-		DeclarationWithType * GenStructMemberCalls::postmutate( FunctionDecl * funcDecl ) {
-			// remove the unhandled objects from usedUninit, because a call is inserted
-			// to handle them - only objects that are later constructed are used uninitialized.
-			std::map< DeclarationWithType *, CodeLocation > diff;
-			// need the comparator since usedUninit and unhandled have different types
-			struct comp_t {
-				typedef decltype(usedUninit)::value_type usedUninit_t;
-				typedef decltype(unhandled)::value_type unhandled_t;
-				bool operator()(usedUninit_t x, unhandled_t y) { return x.first < y; }
-				bool operator()(unhandled_t x, usedUninit_t y) { return x < y.first; }
-			} comp;
-			std::set_difference( usedUninit.begin(), usedUninit.end(), unhandled.begin(), unhandled.end(), std::inserter( diff, diff.begin() ), comp );
-			for ( auto p : diff ) {
-				DeclarationWithType * member = p.first;
-				CodeLocation loc = p.second;
-				// xxx - make error message better by also tracking the location that the object is constructed at?
-				emit( loc, "in ", CodeGen::genPrettyType( function->get_functionType(), function->get_name() ), ", field ", member->get_name(), " used before being constructed" );
-			}
-
-			if ( ! unhandled.empty() ) {
-				// need to explicitly re-add function parameters to the indexer in order to resolve copy constructors
-				auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this]() { indexer.leaveScope(); } );
-				indexer.addFunctionType( function->type );
-
-				// need to iterate through members in reverse in order for
-				// ctor/dtor statements to come out in the right order
-				for ( Declaration * member : reverseIterate( structDecl->get_members() ) ) {
-					DeclarationWithType * field = dynamic_cast< DeclarationWithType * >( member );
-					// skip non-DWT members
-					if ( ! field ) continue;
-					// skip non-constructable members
-					if ( ! tryConstruct( field ) ) continue;
-					// skip handled members
-					if ( ! unhandled.count( field ) ) continue;
-
-					// insert and resolve default/copy constructor call for each field that's unhandled
-					std::list< Statement * > stmt;
-					Expression * arg2 = nullptr;
-					if ( isCopyConstructor( function ) ) {
-						// if copy ctor, need to pass second-param-of-this-function.field
-						std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters();
-						assert( params.size() == 2 );
-						arg2 = new MemberExpr( field, new VariableExpr( params.back() ) );
-					}
-					InitExpander_old srcParam( arg2 );
-					// cast away reference type and construct field.
-					Expression * thisExpr = new CastExpr( new VariableExpr( thisParam ), thisParam->get_type()->stripReferences()->clone() );
-					Expression * memberDest = new MemberExpr( field, thisExpr );
-					SymTab::genImplicitCall( srcParam, memberDest, function->get_name(), back_inserter( stmt ), field, isCtor );
-
-					assert( stmt.size() <= 1 );
-					if ( stmt.size() == 1 ) {
-						Statement * callStmt = stmt.front();
-
-						try {
-							callStmt->acceptMutator( *visitor );
-							if ( isCtor ) {
-								function->statements->push_front( callStmt );
-							} else { // TODO: don't generate destructor function/object for intrinsic calls
-								// destructor statements should be added at the end
-								// function->get_statements()->push_back( callStmt );
-
-								// Optimization: do not need to call intrinsic destructors on members
-								if ( isIntrinsicSingleArgCallStmt( callStmt ) ) continue;;
-
-								// __Destructor _dtor0 = { (void *)&b.a1, (void (*)(void *)_destroy_A };
-								std::list< Statement * > stmtsToAdd;
-
-								static UniqueName memberDtorNamer = { "__memberDtor" };
-								assertf( Validate::dtorStruct, "builtin __Destructor not found." );
-								assertf( Validate::dtorStructDestroy, "builtin __destroy_Destructor not found." );
-
-								Expression * thisExpr = new CastExpr( new AddressExpr( new VariableExpr( thisParam ) ), new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ) );
-								Expression * dtorExpr = new VariableExpr( getDtorFunc( thisParam, callStmt, stmtsToAdd ) );
-
-								// cast destructor pointer to void (*)(void *), to silence GCC incompatible pointer warnings
-								FunctionType * dtorFtype = new FunctionType( Type::Qualifiers(), false );
-								dtorFtype->parameters.push_back( ObjectDecl::newObject( "", new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), nullptr ) );
-								Type * dtorType = new PointerType( Type::Qualifiers(), dtorFtype );
-
-								ObjectDecl * destructor = ObjectDecl::newObject( memberDtorNamer.newName(), new StructInstType( Type::Qualifiers(), Validate::dtorStruct ), new ListInit( { new SingleInit( thisExpr ), new SingleInit( new CastExpr( dtorExpr, dtorType ) ) } ) );
-								function->statements->push_front( new DeclStmt( destructor ) );
-								destructor->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( Validate::dtorStructDestroy ) } ) );
-
-								function->statements->kids.splice( function->statements->kids.begin(), stmtsToAdd );
-							}
-						} catch ( SemanticErrorException & error ) {
-							emit( funcDecl->location, "in ", CodeGen::genPrettyType( function->get_functionType(), function->get_name() ), ", field ", field->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed",  " and no ", isCtor ? "default constructor" : "destructor", " found" );
-						}
-					}
-				}
-			}
-			if (! errors.isEmpty()) {
-				throw errors;
-			}
-			return funcDecl;
-		}
-
-		/// true if expr is effectively just the 'this' parameter
-		bool isThisExpression( Expression * expr, DeclarationWithType * thisParam ) {
-			// TODO: there are more complicated ways to pass 'this' to a constructor, e.g. &*, *&, etc.
-			if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
-				return varExpr->get_var() == thisParam;
-			} else if ( CastExpr * castExpr = dynamic_cast< CastExpr * > ( expr ) ) {
-				return isThisExpression( castExpr->get_arg(), thisParam );
-			}
-			return false;
-		}
-
-		/// returns a MemberExpr if expr is effectively just member access on the 'this' parameter, else nullptr
-		MemberExpr * isThisMemberExpr( Expression * expr, DeclarationWithType * thisParam ) {
-			if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) {
-				if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
-					return memberExpr;
-				}
-			} else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
-				return isThisMemberExpr( castExpr->get_arg(), thisParam );
-			}
-			return nullptr;
-		}
-
-		void GenStructMemberCalls::premutate( ApplicationExpr * appExpr ) {
-			if ( ! checkWarnings( function ) ) {
-				visit_children = false;
-				return;
-			}
-
-			std::string fname = getFunctionName( appExpr );
-			if ( fname == function->name ) {
-				// call to same kind of function
-				Expression * firstParam = appExpr->args.front();
-
-				if ( isThisExpression( firstParam, thisParam ) ) {
-					// if calling another constructor on thisParam, assume that function handles
-					// all members - if it doesn't a warning will appear in that function.
-					unhandled.clear();
-				} else if ( MemberExpr * memberExpr = isThisMemberExpr( firstParam, thisParam ) ) {
-					// if first parameter is a member expression on the this parameter,
-					// then remove the member from unhandled set.
-					if ( isThisExpression( memberExpr->aggregate, thisParam ) ) {
-						unhandled.erase( memberExpr->member );
-					}
-				}
-			}
-		}
-
-		void GenStructMemberCalls::premutate( MemberExpr * memberExpr ) {
-			if ( ! checkWarnings( function ) || ! isCtor ) {
-				visit_children = false;
-				return;
-			}
-
-			if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
-				if ( unhandled.count( memberExpr->get_member() ) ) {
-					// emit a warning because a member was used before it was constructed
-					usedUninit.insert( { memberExpr->get_member(), memberExpr->location } );
-				}
-			}
-		}
-
-		template< typename... Params >
-		void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) {
-			SemanticErrorException err( loc, toString( params... ) );
-			errors.append( err );
-		}
-
-		Expression * GenStructMemberCalls::postmutate( UntypedExpr * untypedExpr ) {
-			Expression * newExpr = untypedExpr;
-			ResolvExpr::findVoidExpression( newExpr, indexer );
-			return newExpr;
-		}
-
-		Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) {
-			static UniqueName tempNamer( "_tmp_ctor_expr" );
-			// xxx - is the size check necessary?
-			assert( ctorExpr->result && ctorExpr->get_result()->size() == 1 );
-
-			// xxx - this can be TupleAssignExpr now. Need to properly handle this case.
-			ApplicationExpr * callExpr = strict_dynamic_cast< ApplicationExpr * > ( ctorExpr->get_callExpr() );
-			TypeSubstitution * env = ctorExpr->get_env();
-			ctorExpr->set_callExpr( nullptr );
-			ctorExpr->set_env( nullptr );
-
-			// xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary.
-			ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), callExpr->args.front()->result->clone(), nullptr );
-			declsToAddBefore.push_back( tmp );
-			delete ctorExpr;
-
-			// build assignment and replace constructor's first argument with new temporary
-			Expression *& firstArg = callExpr->get_args().front();
-			Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } );
-			firstArg = new VariableExpr( tmp );
-
-			// resolve assignment and dispose of new env
-			ResolvExpr::findVoidExpression( assign, indexer );
-			delete assign->env;
-			assign->env = nullptr;
-
-			// for constructor expr:
-			//   T x;
-			//   x{};
-			// results in:
-			//   T x;
-			//   T & tmp;
-			//   &tmp = &x, ?{}(tmp), tmp
-			CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
-			commaExpr->set_env( env );
-			return commaExpr;
-		}
-	} // namespace
-} // namespace InitTweak
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/InitTweak/FixInitNew.cpp
===================================================================
--- src/InitTweak/FixInitNew.cpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/InitTweak/FixInitNew.cpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -178,7 +178,4 @@
 /// (currently by FixInit)
 struct InsertDtors final : public ObjDeclCollector, public ast::WithStmtsToAdd<> {
-	typedef std::list< ObjectDecl * > OrderedDecls;
-	typedef std::list< OrderedDecls > OrderedDeclsStack;
-
 	InsertDtors( ast::Pass<LabelFinder> & finder ) : finder( finder ), labelVars( finder.core.vars ) {}
 
@@ -194,5 +191,4 @@
 	ast::Pass<LabelFinder> & finder;
 	LabelFinder::LabelMap & labelVars;
-	OrderedDeclsStack reverseDeclOrder;
 };
 
@@ -921,5 +917,5 @@
 					// static variables with the same name in different functions.
 					// Note: it isn't sufficient to modify only the mangleName, because
-					// then subsequent Indexer passes can choke on seeing the object's name
+					// then subsequent SymbolTable passes can choke on seeing the object's name
 					// if another object has the same name and type. An unfortunate side-effect
 					// of renaming the object is that subsequent NameExprs may fail to resolve,
@@ -1173,5 +1169,5 @@
 				arg2 = new ast::MemberExpr(funcDecl->location, field, new ast::VariableExpr(funcDecl->location, function->params.back() ) );
 			}
-			InitExpander_new srcParam( arg2 );
+			InitExpander srcParam( arg2 );
 			// cast away reference type and construct field.
 			ast::Expr * thisExpr = new ast::CastExpr(funcDecl->location, new ast::VariableExpr(funcDecl->location, thisParam ), thisParam->get_type()->stripReferences());
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/InitTweak/GenInit.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -29,5 +29,4 @@
 #include "CompilationState.h"
 #include "CodeGen/OperatorTable.h"
-#include "Common/PassVisitor.h"        // for PassVisitor, WithGuards, WithShort...
 #include "Common/SemanticError.h"      // for SemanticError
 #include "Common/ToString.hpp"         // for toCString
@@ -38,272 +37,18 @@
 #include "InitTweak.h"                 // for isConstExpr, InitExpander, checkIn...
 #include "ResolvExpr/Resolver.h"
-#include "SymTab/Autogen.h"            // for genImplicitCall
 #include "SymTab/GenImplicitCall.hpp"  // for genImplicitCall
 #include "SymTab/Mangler.h"            // for Mangler
-#include "SynTree/LinkageSpec.h"       // for isOverridable, C
-#include "SynTree/Declaration.h"       // for ObjectDecl, DeclarationWithType
-#include "SynTree/Expression.h"        // for VariableExpr, UntypedExpr, Address...
-#include "SynTree/Initializer.h"       // for ConstructorInit, SingleInit, Initi...
-#include "SynTree/Label.h"             // for Label
-#include "SynTree/Mutator.h"           // for mutateAll
-#include "SynTree/Statement.h"         // for CompoundStmt, ImplicitCtorDtorStmt
-#include "SynTree/Type.h"              // for Type, ArrayType, Type::Qualifiers
-#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
 #include "Tuples/Tuples.h"             // for maybeImpure
 #include "Validate/FindSpecialDecls.h" // for SizeType
 
 namespace InitTweak {
-	namespace {
-		const std::list<Label> noLabels;
-		const std::list<Expression *> noDesignators;
-	}
-
-	struct ReturnFixer : public WithStmtsToAdd, public WithGuards {
-		/// consistently allocates a temporary variable for the return value
-		/// of a function so that anything which the resolver decides can be constructed
-		/// into the return type of a function can be returned.
-		static void makeReturnTemp( std::list< Declaration * > &translationUnit );
-
-		void premutate( FunctionDecl *functionDecl );
-		void premutate( ReturnStmt * returnStmt );
-
-	  protected:
-		FunctionType * ftype = nullptr;
-		std::string funcName;
-	};
-
-	struct CtorDtor : public WithGuards, public WithShortCircuiting, public WithVisitorRef<CtorDtor>  {
-		/// create constructor and destructor statements for object declarations.
-		/// the actual call statements will be added in after the resolver has run
-		/// so that the initializer expression is only removed if a constructor is found
-		/// and the same destructor call is inserted in all of the appropriate locations.
-		static void generateCtorDtor( std::list< Declaration * > &translationUnit );
-
-		void previsit( ObjectDecl * );
-		void previsit( FunctionDecl *functionDecl );
-
-		// should not traverse into any of these declarations to find objects
-		// that need to be constructed or destructed
-		void previsit( StructDecl *aggregateDecl );
-		void previsit( AggregateDecl * ) { visit_children = false; }
-		void previsit( NamedTypeDecl * ) { visit_children = false; }
-		void previsit( FunctionType * ) { visit_children = false; }
-
-		void previsit( CompoundStmt * compoundStmt );
-
-	  private:
-		// set of mangled type names for which a constructor or destructor exists in the current scope.
-		// these types require a ConstructorInit node to be generated, anything else is a POD type and thus
-		// should not have a ConstructorInit generated.
-
-		ManagedTypes managedTypes;
-		bool inFunction = false;
-	};
-
-	struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards, public WithIndexer {
-		/// hoist dimension from array types in object declaration so that it uses a single
-		/// const variable of type size_t, so that side effecting array dimensions are only
-		/// computed once.
-		static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
-
-		void premutate( ObjectDecl * objectDecl );
-		DeclarationWithType * postmutate( ObjectDecl * objectDecl );
-		void premutate( FunctionDecl *functionDecl );
-		// should not traverse into any of these declarations to find objects
-		// that need to be constructed or destructed
-		void premutate( AggregateDecl * ) { visit_children = false; }
-		void premutate( NamedTypeDecl * ) { visit_children = false; }
-		void premutate( FunctionType * ) { visit_children = false; }
-
-		// need this so that enumerators are added to the indexer, due to premutate(AggregateDecl *)
-		void premutate( EnumDecl * ) {}
-
-		void hoist( Type * type );
-
-		Type::StorageClasses storageClasses;
-		bool inFunction = false;
-	};
-
-	struct HoistArrayDimension_NoResolve final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards {
-		/// hoist dimension from array types in object declaration so that it uses a single
-		/// const variable of type size_t, so that side effecting array dimensions are only
-		/// computed once.
-		static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
-
-		void premutate( ObjectDecl * objectDecl );
-		DeclarationWithType * postmutate( ObjectDecl * objectDecl );
-		void premutate( FunctionDecl *functionDecl );
-		// should not traverse into any of these declarations to find objects
-		// that need to be constructed or destructed
-		void premutate( AggregateDecl * ) { visit_children = false; }
-		void premutate( NamedTypeDecl * ) { visit_children = false; }
-		void premutate( FunctionType * ) { visit_children = false; }
-
-		void hoist( Type * type );
-
-		Type::StorageClasses storageClasses;
-		bool inFunction = false;
-	};
-
-	void genInit( std::list< Declaration * > & translationUnit ) {
-		if (!useNewAST) {
-			HoistArrayDimension::hoistArrayDimension( translationUnit );
-		}
-		else {
-			HoistArrayDimension_NoResolve::hoistArrayDimension( translationUnit );
-		}
-		fixReturnStatements( translationUnit );
-
-		if (!useNewAST) {
-			CtorDtor::generateCtorDtor( translationUnit );
-		}
-	}
-
-	void fixReturnStatements( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<ReturnFixer> fixer;
-		mutateAll( translationUnit, fixer );
-	}
-
-	void ReturnFixer::premutate( ReturnStmt *returnStmt ) {
-		std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals();
-		assert( returnVals.size() == 0 || returnVals.size() == 1 );
-		// hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address
-		// is being returned
-		if ( returnStmt->expr && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) {
-			// explicitly construct the return value using the return expression and the retVal object
-			assertf( returnVals.front()->name != "", "Function %s has unnamed return value\n", funcName.c_str() );
-
-			ObjectDecl * retVal = strict_dynamic_cast< ObjectDecl * >( returnVals.front() );
-			if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( returnStmt->expr ) ) {
-				// return statement has already been mutated - don't need to do it again
-				if ( varExpr->var == retVal ) return;
-			}
-			Statement * stmt = genCtorDtor( "?{}", retVal, returnStmt->expr );
-			assertf( stmt, "ReturnFixer: genCtorDtor returned nullptr: %s / %s", toString( retVal ).c_str(), toString( returnStmt->expr ).c_str() );
-			stmtsToAddBefore.push_back( stmt );
-
-			// return the retVal object
-			returnStmt->expr = new VariableExpr( returnVals.front() );
-		} // if
-	}
-
-	void ReturnFixer::premutate( FunctionDecl *functionDecl ) {
-		GuardValue( ftype );
-		GuardValue( funcName );
-
-		ftype = functionDecl->type;
-		funcName = functionDecl->name;
-	}
-
-	// precompute array dimension expression, because constructor generation may duplicate it,
-	// which would be incorrect if it is a side-effecting computation.
-	void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<HoistArrayDimension> hoister;
-		mutateAll( translationUnit, hoister );
-	}
-
-	void HoistArrayDimension::premutate( ObjectDecl * objectDecl ) {
-		GuardValue( storageClasses );
-		storageClasses = objectDecl->get_storageClasses();
-	}
-
-	DeclarationWithType * HoistArrayDimension::postmutate( ObjectDecl * objectDecl ) {
-		hoist( objectDecl->get_type() );
-		return objectDecl;
-	}
-
-	void HoistArrayDimension::hoist( Type * type ) {
-		// if in function, generate const size_t var
-		static UniqueName dimensionName( "_array_dim" );
-
-		// C doesn't allow variable sized arrays at global scope or for static variables, so don't hoist dimension.
-		if ( ! inFunction ) return;
-		if ( storageClasses.is_static ) return;
-
-		if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
-			if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
-
-			// need to resolve array dimensions in order to accurately determine if constexpr
-			ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
-			// array is variable-length when the dimension is not constexpr
-			arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
-			// don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
-			// xxx - hoisting has no side effects anyways, so don't skip since we delay resolve
-			// still try to detect constant expressions
-			if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
-
-			ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
-			arrayDimension->get_type()->set_const( true );
-
-			arrayType->set_dimension( new VariableExpr( arrayDimension ) );
-			declsToAddBefore.push_back( arrayDimension );
-
-			hoist( arrayType->get_base() );
-			return;
-		}
-	}
-
-	void HoistArrayDimension::premutate( FunctionDecl * ) {
-		GuardValue( inFunction );
-		inFunction = true;
-	}
-
-	// precompute array dimension expression, because constructor generation may duplicate it,
-	// which would be incorrect if it is a side-effecting computation.
-	void HoistArrayDimension_NoResolve::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<HoistArrayDimension_NoResolve> hoister;
-		mutateAll( translationUnit, hoister );
-	}
-
-	void HoistArrayDimension_NoResolve::premutate( ObjectDecl * objectDecl ) {
-		GuardValue( storageClasses );
-		storageClasses = objectDecl->get_storageClasses();
-	}
-
-	DeclarationWithType * HoistArrayDimension_NoResolve::postmutate( ObjectDecl * objectDecl ) {
-		hoist( objectDecl->get_type() );
-		return objectDecl;
-	}
-
-	void HoistArrayDimension_NoResolve::hoist( Type * type ) {
-		// if in function, generate const size_t var
-		static UniqueName dimensionName( "_array_dim" );
-
-		// C doesn't allow variable sized arrays at global scope or for static variables, so don't hoist dimension.
-		if ( ! inFunction ) return;
-		if ( storageClasses.is_static ) return;
-
-		if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
-			if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
-			// don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
-			// xxx - hoisting has no side effects anyways, so don't skip since we delay resolve
-			// still try to detect constant expressions
-			if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
-
-			ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
-			arrayDimension->get_type()->set_const( true );
-
-			arrayType->set_dimension( new VariableExpr( arrayDimension ) );
-			declsToAddBefore.push_back( arrayDimension );
-
-			hoist( arrayType->get_base() );
-			return;
-		}
-	}
-
-	void HoistArrayDimension_NoResolve::premutate( FunctionDecl * ) {
-		GuardValue( inFunction );
-		inFunction = true;
-	}
 
 namespace {
 
-#	warning Remove the _New suffix after the conversion is complete.
-
 	// Outer pass finds declarations, for their type could wrap a type that needs hoisting
-	struct HoistArrayDimension_NoResolve_New final :
+	struct HoistArrayDimension_NoResolve final :
 			public ast::WithDeclsToAdd<>, public ast::WithShortCircuiting,
 			public ast::WithGuards, public ast::WithConstTranslationUnit,
-			public ast::WithVisitorRef<HoistArrayDimension_NoResolve_New>,
+			public ast::WithVisitorRef<HoistArrayDimension_NoResolve>,
 			public ast::WithSymbolTableX<ast::SymbolTable::ErrorDetection::IgnoreErrors> {
 
@@ -312,6 +57,6 @@
 				public ast::WithShortCircuiting, public ast::WithGuards {
 
-			HoistArrayDimension_NoResolve_New * outer;
-			HoistDimsFromTypes( HoistArrayDimension_NoResolve_New * outer ) : outer(outer) {}
+			HoistArrayDimension_NoResolve * outer;
+			HoistDimsFromTypes( HoistArrayDimension_NoResolve * outer ) : outer(outer) {}
 
 			// Only intended for visiting through types.
@@ -464,5 +209,5 @@
 
 
-	struct ReturnFixer_New final :
+	struct ReturnFixer final :
 			public ast::WithStmtsToAdd<>, ast::WithGuards, ast::WithShortCircuiting {
 		void previsit( const ast::FunctionDecl * decl );
@@ -472,10 +217,10 @@
 	};
 
-	void ReturnFixer_New::previsit( const ast::FunctionDecl * decl ) {
+	void ReturnFixer::previsit( const ast::FunctionDecl * decl ) {
 		if (decl->linkage == ast::Linkage::Intrinsic) visit_children = false;
 		GuardValue( funcDecl ) = decl;
 	}
 
-	const ast::ReturnStmt * ReturnFixer_New::previsit(
+	const ast::ReturnStmt * ReturnFixer::previsit(
 			const ast::ReturnStmt * stmt ) {
 		auto & returns = funcDecl->returns;
@@ -518,75 +263,13 @@
 
 	void genInit( ast::TranslationUnit & transUnit ) {
-		ast::Pass<HoistArrayDimension_NoResolve_New>::run( transUnit );
-		ast::Pass<ReturnFixer_New>::run( transUnit );
+		ast::Pass<HoistArrayDimension_NoResolve>::run( transUnit );
+		ast::Pass<ReturnFixer>::run( transUnit );
 	}
 
 	void fixReturnStatements( ast::TranslationUnit & transUnit ) {
-		ast::Pass<ReturnFixer_New>::run( transUnit );
-	}
-
-	void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<CtorDtor> ctordtor;
-		acceptAll( translationUnit, ctordtor );
-	}
-
-	bool ManagedTypes::isManaged( Type * type ) const {
-		// references are never constructed
-		if ( dynamic_cast< ReferenceType * >( type ) ) return false;
-		// need to clear and reset qualifiers when determining if a type is managed
-		ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
-		type->get_qualifiers() = Type::Qualifiers();
-		if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
-			// tuple is also managed if any of its components are managed
-			if ( std::any_of( tupleType->types.begin(), tupleType->types.end(), [&](Type * type) { return isManaged( type ); }) ) {
-				return true;
-			}
-		}
-		// a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable)
-		return managedTypes.find( SymTab::Mangler::mangleConcrete( type ) ) != managedTypes.end() || GenPoly::isPolyType( type );
-	}
-
-	bool ManagedTypes::isManaged( ObjectDecl * objDecl ) const {
-		Type * type = objDecl->get_type();
-		while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
-			// must always construct VLAs with an initializer, since this is an error in C
-			if ( at->isVarLen && objDecl->init ) return true;
-			type = at->get_base();
-		}
-		return isManaged( type );
-	}
-
-	// why is this not just on FunctionDecl?
-	void ManagedTypes::handleDWT( DeclarationWithType * dwt ) {
-		// if this function is a user-defined constructor or destructor, mark down the type as "managed"
-		if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) {
-			std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters();
-			assert( ! params.empty() );
-			Type * type = InitTweak::getPointerBase( params.front()->get_type() );
-			assert( type );
-			managedTypes.insert( SymTab::Mangler::mangleConcrete( type ) );
-		}
-	}
-
-	void ManagedTypes::handleStruct( StructDecl * aggregateDecl ) {
-		// don't construct members, but need to take note if there is a managed member,
-		// because that means that this type is also managed
-		for ( Declaration * member : aggregateDecl->get_members() ) {
-			if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
-				if ( isManaged( field ) ) {
-					// generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that
-					// polymorphic constructors make generic types managed types
-					StructInstType inst( Type::Qualifiers(), aggregateDecl );
-					managedTypes.insert( SymTab::Mangler::mangleConcrete( &inst ) );
-					break;
-				}
-			}
-		}
-	}
-
-	void ManagedTypes::beginScope() { managedTypes.beginScope(); }
-	void ManagedTypes::endScope() { managedTypes.endScope(); }
-
-	bool ManagedTypes_new::isManaged( const ast::Type * type ) const {
+		ast::Pass<ReturnFixer>::run( transUnit );
+	}
+
+	bool ManagedTypes::isManaged( const ast::Type * type ) const {
 		// references are never constructed
 		if ( dynamic_cast< const ast::ReferenceType * >( type ) ) return false;
@@ -607,5 +290,5 @@
 	}
 
-	bool ManagedTypes_new::isManaged( const ast::ObjectDecl * objDecl ) const {
+	bool ManagedTypes::isManaged( const ast::ObjectDecl * objDecl ) const {
 		const ast::Type * type = objDecl->type;
 		while ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
@@ -617,5 +300,5 @@
 	}
 
-	void ManagedTypes_new::handleDWT( const ast::DeclWithType * dwt ) {
+	void ManagedTypes::handleDWT( const ast::DeclWithType * dwt ) {
 		// if this function is a user-defined constructor or destructor, mark down the type as "managed"
 		if ( ! dwt->linkage.is_overrideable && CodeGen::isCtorDtor( dwt->name ) ) {
@@ -628,5 +311,5 @@
 	}
 
-	void ManagedTypes_new::handleStruct( const ast::StructDecl * aggregateDecl ) {
+	void ManagedTypes::handleStruct( const ast::StructDecl * aggregateDecl ) {
 		// don't construct members, but need to take note if there is a managed member,
 		// because that means that this type is also managed
@@ -644,96 +327,11 @@
 	}
 
-	void ManagedTypes_new::beginScope() { managedTypes.beginScope(); }
-	void ManagedTypes_new::endScope() { managedTypes.endScope(); }
-
-	ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) {
-		// call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
-		assertf( objDecl, "genCtorDtor passed null objDecl" );
-		std::list< Statement * > stmts;
-		InitExpander_old srcParam( maybeClone( arg ) );
-		SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), fname, back_inserter( stmts ), objDecl );
-		assert( stmts.size() <= 1 );
-		return stmts.size() == 1 ? strict_dynamic_cast< ImplicitCtorDtorStmt * >( stmts.front() ) : nullptr;
-
-	}
+	void ManagedTypes::beginScope() { managedTypes.beginScope(); }
+	void ManagedTypes::endScope() { managedTypes.endScope(); }
 
 	ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) {
 		assertf(objDecl, "genCtorDtor passed null objDecl");
-		InitExpander_new srcParam(arg);
+		InitExpander srcParam(arg);
 		return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl);
-	}
-
-	ConstructorInit * genCtorInit( ObjectDecl * objDecl ) {
-		// call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
-		// for each constructable object
-		std::list< Statement * > ctor;
-		std::list< Statement * > dtor;
-
-		InitExpander_old srcParam( objDecl->get_init() );
-		InitExpander_old nullParam( (Initializer *)NULL );
-		SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
-		SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
-
-		// Currently genImplicitCall produces a single Statement - a CompoundStmt
-		// which  wraps everything that needs to happen. As such, it's technically
-		// possible to use a Statement ** in the above calls, but this is inherently
-		// unsafe, so instead we take the slightly less efficient route, but will be
-		// immediately informed if somehow the above assumption is broken. In this case,
-		// we could always wrap the list of statements at this point with a CompoundStmt,
-		// but it seems reasonable at the moment for this to be done by genImplicitCall
-		// itself. It is possible that genImplicitCall produces no statements (e.g. if
-		// an array type does not have a dimension). In this case, it's fine to ignore
-		// the object for the purposes of construction.
-		assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
-		if ( ctor.size() == 1 ) {
-			// need to remember init expression, in case no ctors exist
-			// if ctor does exist, want to use ctor expression instead of init
-			// push this decision to the resolver
-			assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
-			return new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() );
-		}
-		return nullptr;
-	}
-
-	void CtorDtor::previsit( ObjectDecl * objDecl ) {
-		managedTypes.handleDWT( objDecl );
-		// hands off if @=, extern, builtin, etc.
-		// even if unmanaged, try to construct global or static if initializer is not constexpr, since this is not legal C
-		if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {
-			// constructed objects cannot be designated
-			if ( isDesignated( objDecl->get_init() ) ) SemanticError( objDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
-			// constructed objects should not have initializers nested too deeply
-			if ( ! checkInitDepth( objDecl ) ) SemanticError( objDecl, "Managed object's initializer is too deep " );
-
-			objDecl->set_init( genCtorInit( objDecl ) );
-		}
-	}
-
-	void CtorDtor::previsit( FunctionDecl *functionDecl ) {
-		visit_children = false;  // do not try and construct parameters or forall parameters
-		GuardValue( inFunction );
-		inFunction = true;
-
-		managedTypes.handleDWT( functionDecl );
-
-		GuardScope( managedTypes );
-		// go through assertions and recursively add seen ctor/dtors
-		for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
-			for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
-				managedTypes.handleDWT( assertion );
-			}
-		}
-
-		maybeAccept( functionDecl->get_statements(), *visitor );
-	}
-
-	void CtorDtor::previsit( StructDecl *aggregateDecl ) {
-		visit_children = false; // do not try to construct and destruct aggregate members
-
-		managedTypes.handleStruct( aggregateDecl );
-	}
-
-	void CtorDtor::previsit( CompoundStmt * ) {
-		GuardScope( managedTypes );
 	}
 
@@ -741,5 +339,5 @@
 	// call into genImplicitCall from Autogen.h to generate calls to ctor/dtor for each
 	// constructable object
-	InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr };
+	InitExpander srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr };
 	ast::ptr< ast::Expr > dstParam = new ast::VariableExpr(loc, objDecl);
 
Index: src/InitTweak/GenInit.h
===================================================================
--- src/InitTweak/GenInit.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/InitTweak/GenInit.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -22,39 +22,20 @@
 #include "Common/CodeLocation.h"
 #include "GenPoly/ScopedSet.h" // for ScopedSet
-#include "SynTree/SynTree.h"   // for Visitor Nodes
 
 namespace InitTweak {
 	/// Adds return value temporaries and wraps Initializers in ConstructorInit nodes
-	void genInit( std::list< Declaration * > & translationUnit );
 	void genInit( ast::TranslationUnit & translationUnit );
 
 	/// Converts return statements into copy constructor calls on the hidden return variable.
 	/// This pass must happen before auto-gen.
-	void fixReturnStatements( std::list< Declaration * > & translationUnit );
 	void fixReturnStatements( ast::TranslationUnit & translationUnit );
 
 	/// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
-	ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr );
 	ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr);
 
 	/// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
-	ConstructorInit * genCtorInit( ObjectDecl * objDecl );
 	ast::ConstructorInit * genCtorInit( const CodeLocation & loc, const ast::ObjectDecl * objDecl );
 
-	class ManagedTypes {
-	public:
-		bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
-		bool isManaged( Type * type ) const; // determine if type is managed
-
-		void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
-		void handleStruct( StructDecl * aggregateDecl ); // add type to managed if child is managed
-
-		void beginScope();
-		void endScope();
-	private:
-		GenPoly::ScopedSet< std::string > managedTypes;
-	};
-
-	class ManagedTypes_new {
+	class ManagedTypes final {
 	public:
 		bool isManaged( const ast::ObjectDecl * objDecl ) const ; // determine if object is managed
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/InitTweak/InitTweak.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -29,5 +29,4 @@
 #include "AST/Type.hpp"
 #include "CodeGen/OperatorTable.h" // for isConstructor, isDestructor, isCto...
-#include "Common/PassVisitor.h"
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/UniqueName.h"     // for UniqueName
@@ -36,58 +35,9 @@
 #include "InitTweak.h"
 #include "ResolvExpr/Unify.h"      // for typesCompatibleIgnoreQualifiers
-#include "SymTab/Autogen.h"
-#include "SymTab/Indexer.h"        // for Indexer
-#include "SynTree/LinkageSpec.h"   // for Spec, isBuiltin, Intrinsic
-#include "SynTree/Attribute.h"     // for Attribute
-#include "SynTree/Constant.h"      // for Constant
-#include "SynTree/Declaration.h"   // for ObjectDecl, DeclarationWithType
-#include "SynTree/Expression.h"    // for Expression, UntypedExpr, Applicati...
-#include "SynTree/Initializer.h"   // for Initializer, ListInit, Designation
-#include "SynTree/Label.h"         // for Label
-#include "SynTree/Statement.h"     // for CompoundStmt, ExprStmt, BranchStmt
-#include "SynTree/Type.h"          // for FunctionType, ArrayType, PointerType
-#include "SynTree/Visitor.h"       // for Visitor, maybeAccept
 #include "Tuples/Tuples.h"         // for Tuples::isTtype
 
 namespace InitTweak {
 	namespace {
-		struct HasDesignations : public WithShortCircuiting {
-			bool hasDesignations = false;
-
-			void previsit( BaseSyntaxNode * ) {
-				// short circuit if we already know there are designations
-				if ( hasDesignations ) visit_children = false;
-			}
-
-			void previsit( Designation * des ) {
-				// short circuit if we already know there are designations
-				if ( hasDesignations ) visit_children = false;
-				else if ( ! des->get_designators().empty() ) {
-					hasDesignations = true;
-					visit_children = false;
-				}
-			}
-		};
-
-		struct InitDepthChecker : public WithGuards {
-			bool depthOkay = true;
-			Type * type;
-			int curDepth = 0, maxDepth = 0;
-			InitDepthChecker( Type * type ) : type( type ) {
-				Type * t = type;
-				while ( ArrayType * at = dynamic_cast< ArrayType * >( t ) ) {
-					maxDepth++;
-					t = at->get_base();
-				}
-				maxDepth++;
-			}
-			void previsit( ListInit * ) {
-				curDepth++;
-				GuardAction( [this]() { curDepth--; } );
-				if ( curDepth > maxDepth ) depthOkay = false;
-			}
-		};
-
-		struct HasDesignations_new : public ast::WithShortCircuiting {
+		struct HasDesignations : public ast::WithShortCircuiting {
 			bool result = false;
 
@@ -107,9 +57,9 @@
 		};
 
-		struct InitDepthChecker_new {
+		struct InitDepthChecker {
 			bool result = true;
 			const ast::Type * type;
 			int curDepth = 0, maxDepth = 0;
-			InitDepthChecker_new( const ast::Type * type ) : type( type ) {
+			InitDepthChecker( const ast::Type * type ) : type( type ) {
 				const ast::Type * t = type;
 				while ( auto at = dynamic_cast< const ast::ArrayType * >( t ) ) {
@@ -128,13 +78,5 @@
 		};
 
-		struct InitFlattener_old : public WithShortCircuiting {
-			void previsit( SingleInit * singleInit ) {
-				visit_children = false;
-				argList.push_back( singleInit->value->clone() );
-			}
-			std::list< Expression * > argList;
-		};
-
-		struct InitFlattener_new : public ast::WithShortCircuiting {
+		struct InitFlattener : public ast::WithShortCircuiting {
 			std::vector< ast::ptr< ast::Expr > > argList;
 
@@ -147,24 +89,6 @@
 	} // anonymous namespace
 
-	std::list< Expression * > makeInitList( Initializer * init ) {
-		PassVisitor<InitFlattener_old> flattener;
-		maybeAccept( init, flattener );
-		return flattener.pass.argList;
-	}
-
-	bool isDesignated( Initializer * init ) {
-		PassVisitor<HasDesignations> finder;
-		maybeAccept( init, finder );
-		return finder.pass.hasDesignations;
-	}
-
-	bool checkInitDepth( ObjectDecl * objDecl ) {
-		PassVisitor<InitDepthChecker> checker( objDecl->type );
-		maybeAccept( objDecl->init, checker );
-		return checker.pass.depthOkay;
-	}
-
 	bool isDesignated( const ast::Init * init ) {
-		ast::Pass<HasDesignations_new> finder;
+		ast::Pass<HasDesignations> finder;
 		maybe_accept( init, finder );
 		return finder.core.result;
@@ -172,5 +96,5 @@
 
 	bool checkInitDepth( const ast::ObjectDecl * objDecl ) {
-		ast::Pass<InitDepthChecker_new> checker( objDecl->type );
+		ast::Pass<InitDepthChecker> checker( objDecl->type );
 		maybe_accept( objDecl->init.get(), checker );
 		return checker.core.result;
@@ -178,194 +102,10 @@
 
 std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ) {
-	ast::Pass< InitFlattener_new > flattener;
+	ast::Pass< InitFlattener > flattener;
 	maybe_accept( init, flattener );
 	return std::move( flattener.core.argList );
 }
 
-	class InitExpander_old::ExpanderImpl {
-	public:
-		virtual ~ExpanderImpl() = default;
-		virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0;
-		virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0;
-	};
-
-	class InitImpl_old : public InitExpander_old::ExpanderImpl {
-	public:
-		InitImpl_old( Initializer * init ) : init( init ) {}
-		virtual ~InitImpl_old() = default;
-
-		virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) {
-			// this is wrong, but just a placeholder for now
-			// if ( ! flattened ) flatten( indices );
-			// return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
-			return makeInitList( init );
-		}
-
-		virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
-	private:
-		Initializer * init;
-	};
-
-	class ExprImpl_old : public InitExpander_old::ExpanderImpl {
-	public:
-		ExprImpl_old( Expression * expr ) : arg( expr ) {}
-		virtual ~ExprImpl_old() { delete arg; }
-
-		virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
-			std::list< Expression * > ret;
-			Expression * expr = maybeClone( arg );
-			if ( expr ) {
-				for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) {
-					// go through indices and layer on subscript exprs ?[?]
-					++it;
-					UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") );
-					subscriptExpr->get_args().push_back( expr );
-					subscriptExpr->get_args().push_back( (*it)->clone() );
-					expr = subscriptExpr;
-				}
-				ret.push_back( expr );
-			}
-			return ret;
-		}
-
-		virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
-	private:
-		Expression * arg;
-	};
-
-	InitExpander_old::InitExpander_old( Initializer * init ) : expander( new InitImpl_old( init ) ) {}
-
-	InitExpander_old::InitExpander_old( Expression * expr ) : expander( new ExprImpl_old( expr ) ) {}
-
-	std::list< Expression * > InitExpander_old::operator*() {
-		return cur;
-	}
-
-	InitExpander_old & InitExpander_old::operator++() {
-		cur = expander->next( indices );
-		return *this;
-	}
-
-	// use array indices list to build switch statement
-	void InitExpander_old::addArrayIndex( Expression * index, Expression * dimension ) {
-		indices.push_back( index );
-		indices.push_back( dimension );
-	}
-
-	void InitExpander_old::clearArrayIndices() {
-		deleteAll( indices );
-		indices.clear();
-	}
-
-	bool InitExpander_old::addReference() {
-		bool added = false;
-		for ( Expression *& expr : cur ) {
-			expr = new AddressExpr( expr );
-			added = true;
-		}
-		return added;
-	}
-
-	namespace {
-		/// given index i, dimension d, initializer init, and callExpr f, generates
-		///   if (i < d) f(..., init)
-		///   ++i;
-		/// so that only elements within the range of the array are constructed
-		template< typename OutIterator >
-		void buildCallExpr( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
-			UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
-			cond->get_args().push_back( index->clone() );
-			cond->get_args().push_back( dimension->clone() );
-
-			std::list< Expression * > args = makeInitList( init );
-			callExpr->get_args().splice( callExpr->get_args().end(), args );
-
-			*out++ = new IfStmt( cond, new ExprStmt( callExpr ), nullptr );
-
-			UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
-			increment->get_args().push_back( index->clone() );
-			*out++ = new ExprStmt( increment );
-		}
-
-		template< typename OutIterator >
-		void build( UntypedExpr * callExpr, InitExpander_old::IndexList::iterator idx, InitExpander_old::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
-			if ( idx == idxEnd ) return;
-			Expression * index = *idx++;
-			assert( idx != idxEnd );
-			Expression * dimension = *idx++;
-
-			// xxx - may want to eventually issue a warning here if we can detect
-			// that the number of elements exceeds to dimension of the array
-			if ( idx == idxEnd ) {
-				if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {
-					for ( Initializer * init : *listInit ) {
-						buildCallExpr( callExpr->clone(), index, dimension, init, out );
-					}
-				} else {
-					buildCallExpr( callExpr->clone(), index, dimension, init, out );
-				}
-			} else {
-				std::list< Statement * > branches;
-
-				unsigned long cond = 0;
-				ListInit * listInit = dynamic_cast< ListInit * >( init );
-				if ( ! listInit ) {
-					// xxx - this shouldn't be an error, but need a way to
-					// terminate without creating output, so should catch this error
-					SemanticError( init->location, "unbalanced list initializers" );
-				}
-
-				static UniqueName targetLabel( "L__autogen__" );
-				Label switchLabel( targetLabel.newName(), 0, std::list< Attribute * >{ new Attribute("unused") } );
-				for ( Initializer * init : *listInit ) {
-					Expression * condition;
-					// check for designations
-					// if ( init-> ) {
-						condition = new ConstantExpr( Constant::from_ulong( cond ) );
-						++cond;
-					// } else {
-					// 	condition = // ... take designation
-					// 	cond = // ... take designation+1
-					// }
-					std::list< Statement * > stmts;
-					build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
-					stmts.push_back( new BranchStmt( switchLabel, BranchStmt::Break ) );
-					CaseStmt * caseStmt = new CaseStmt( condition, stmts );
-					branches.push_back( caseStmt );
-				}
-				*out++ = new SwitchStmt( index->clone(), branches );
-				*out++ = new NullStmt( { switchLabel } );
-			}
-		}
-	}
-
-	// if array came with an initializer list: initialize each element
-	// may have more initializers than elements in the array - need to check at each index that
-	// we haven't exceeded size.
-	// may have fewer initializers than elements in the array - need to default construct
-	// remaining elements.
-	// To accomplish this, generate switch statement, consuming all of expander's elements
-	Statement * InitImpl_old::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
-		if ( ! init ) return nullptr;
-		CompoundStmt * block = new CompoundStmt();
-		build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
-		if ( block->get_kids().empty() ) {
-			delete block;
-			return nullptr;
-		} else {
-			init = nullptr; // init was consumed in creating the list init
-			return block;
-		}
-	}
-
-	Statement * ExprImpl_old::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
-		return nullptr;
-	}
-
-	Statement * InitExpander_old::buildListInit( UntypedExpr * dst ) {
-		return expander->buildListInit( dst, indices );
-	}
-
-class InitExpander_new::ExpanderImpl {
+class InitExpander::ExpanderImpl {
 public:
 	virtual ~ExpanderImpl() = default;
@@ -397,5 +137,5 @@
 	template< typename Out >
 	void build(
-		ast::UntypedExpr * callExpr, const InitExpander_new::IndexList & indices,
+		ast::UntypedExpr * callExpr, const InitExpander::IndexList & indices,
 		const ast::Init * init, Out & out
 	) {
@@ -443,15 +183,15 @@
 	}
 
-	class InitImpl_new final : public InitExpander_new::ExpanderImpl {
+	class InitImpl final : public InitExpander::ExpanderImpl {
 		ast::ptr< ast::Init > init;
 	public:
-		InitImpl_new( const ast::Init * i ) : init( i ) {}
-
-		std::vector< ast::ptr< ast::Expr > > next( InitExpander_new::IndexList & ) override {
+		InitImpl( const ast::Init * i ) : init( i ) {}
+
+		std::vector< ast::ptr< ast::Expr > > next( InitExpander::IndexList & ) override {
 			return makeInitList( init );
 		}
 
 		ast::ptr< ast::Stmt > buildListInit(
-			ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices
+			ast::UntypedExpr * callExpr, InitExpander::IndexList & indices
 		) override {
 			// If array came with an initializer list, initialize each element. We may have more
@@ -475,11 +215,11 @@
 	};
 
-	class ExprImpl_new final : public InitExpander_new::ExpanderImpl {
+	class ExprImpl final : public InitExpander::ExpanderImpl {
 		ast::ptr< ast::Expr > arg;
 	public:
-		ExprImpl_new( const ast::Expr * a ) : arg( a ) {}
+		ExprImpl( const ast::Expr * a ) : arg( a ) {}
 
 		std::vector< ast::ptr< ast::Expr > > next(
-			InitExpander_new::IndexList & indices
+			InitExpander::IndexList & indices
 		) override {
 			if ( ! arg ) return {};
@@ -497,5 +237,5 @@
 
 		ast::ptr< ast::Stmt > buildListInit(
-			ast::UntypedExpr *, InitExpander_new::IndexList &
+			ast::UntypedExpr *, InitExpander::IndexList &
 		) override {
 			return {};
@@ -504,13 +244,13 @@
 } // anonymous namespace
 
-InitExpander_new::InitExpander_new( const ast::Init * init )
-: expander( new InitImpl_new{ init } ), crnt(), indices() {}
-
-InitExpander_new::InitExpander_new( const ast::Expr * expr )
-: expander( new ExprImpl_new{ expr } ), crnt(), indices() {}
-
-std::vector< ast::ptr< ast::Expr > > InitExpander_new::operator* () { return crnt; }
-
-InitExpander_new & InitExpander_new::operator++ () {
+InitExpander::InitExpander( const ast::Init * init )
+: expander( new InitImpl{ init } ), crnt(), indices() {}
+
+InitExpander::InitExpander( const ast::Expr * expr )
+: expander( new ExprImpl{ expr } ), crnt(), indices() {}
+
+std::vector< ast::ptr< ast::Expr > > InitExpander::operator* () { return crnt; }
+
+InitExpander & InitExpander::operator++ () {
 	crnt = expander->next( indices );
 	return *this;
@@ -519,16 +259,16 @@
 /// builds statement which has the same semantics as a C-style list initializer (for array
 /// initializers) using callExpr as the base expression to perform initialization
-ast::ptr< ast::Stmt > InitExpander_new::buildListInit( ast::UntypedExpr * callExpr ) {
+ast::ptr< ast::Stmt > InitExpander::buildListInit( ast::UntypedExpr * callExpr ) {
 	return expander->buildListInit( callExpr, indices );
 }
 
-void InitExpander_new::addArrayIndex( const ast::Expr * index, const ast::Expr * dimension ) {
+void InitExpander::addArrayIndex( const ast::Expr * index, const ast::Expr * dimension ) {
 	indices.emplace_back( index );
 	indices.emplace_back( dimension );
 }
 
-void InitExpander_new::clearArrayIndices() { indices.clear(); }
-
-bool InitExpander_new::addReference() {
+void InitExpander::clearArrayIndices() { indices.clear(); }
+
+bool InitExpander::addReference() {
 	for ( ast::ptr< ast::Expr > & expr : crnt ) {
 		expr = new ast::AddressExpr{ expr };
@@ -536,11 +276,4 @@
 	return ! crnt.empty();
 }
-
-	Type * getTypeofThis( FunctionType * ftype ) {
-		assertf( ftype, "getTypeofThis: nullptr ftype" );
-		ObjectDecl * thisParam = getParamThis( ftype );
-		ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( thisParam->type );
-		return refType->base;
-	}
 
 	const ast::Type * getTypeofThis( const ast::FunctionType * ftype ) {
@@ -554,11 +287,4 @@
 	}
 
-	ObjectDecl * getParamThis( FunctionType * ftype ) {
-		assertf( ftype, "getParamThis: nullptr ftype" );
-		auto & params = ftype->parameters;
-		assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( ftype ).c_str() );
-		return strict_dynamic_cast< ObjectDecl * >( params.front() );
-	}
-
 	const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func) {
 		assertf( func, "getParamThis: nullptr ftype" );
@@ -566,17 +292,4 @@
 		assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( func ).c_str());
 		return params.front().strict_as<ast::ObjectDecl>();
-	}
-
-	bool tryConstruct( DeclarationWithType * dwt ) {
-		ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt );
-		if ( ! objDecl ) return false;
-		return (objDecl->get_init() == nullptr ||
-				( objDecl->get_init() != nullptr && objDecl->get_init()->get_maybeConstructed() ))
-			&& ! objDecl->get_storageClasses().is_extern
-			&& isConstructable( objDecl->type );
-	}
-
-	bool isConstructable( Type * type ) {
-		return ! dynamic_cast< VarArgsType * >( type ) && ! dynamic_cast< ReferenceType * >( type ) && ! dynamic_cast< FunctionType * >( type ) && ! Tuples::isTtype( type );
 	}
 
@@ -595,33 +308,9 @@
 	}
 
-	struct CallFinder_old {
-		CallFinder_old( const std::list< std::string > & names ) : names( names ) {}
-
-		void postvisit( ApplicationExpr * appExpr ) {
-			handleCallExpr( appExpr );
-		}
-
-		void postvisit( UntypedExpr * untypedExpr ) {
-			handleCallExpr( untypedExpr );
-		}
-
-		std::list< Expression * > * matches;
-	private:
-		const std::list< std::string > names;
-
-		template< typename CallExpr >
-		void handleCallExpr( CallExpr * expr ) {
-			std::string fname = getFunctionName( expr );
-			if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
-				matches->push_back( expr );
-			}
-		}
-	};
-
-	struct CallFinder_new final {
+	struct CallFinder final {
 		std::vector< const ast::Expr * > matches;
 		const std::vector< std::string > names;
 
-		CallFinder_new( std::vector< std::string > && ns ) : matches(), names( std::move(ns) ) {}
+		CallFinder( std::vector< std::string > && ns ) : matches(), names( std::move(ns) ) {}
 
 		void handleCallExpr( const ast::Expr * expr ) {
@@ -636,91 +325,11 @@
 	};
 
-	void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
-		static PassVisitor<CallFinder_old> finder( std::list< std::string >{ "?{}", "^?{}" } );
-		finder.pass.matches = &matches;
-		maybeAccept( stmt, finder );
-	}
-
 	std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ) {
-		ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } };
+		ast::Pass< CallFinder > finder{ std::vector< std::string >{ "?{}", "^?{}" } };
 		maybe_accept( stmt, finder );
 		return std::move( finder.core.matches );
 	}
 
-	Expression * getCtorDtorCall( Statement * stmt ) {
-		std::list< Expression * > matches;
-		collectCtorDtorCalls( stmt, matches );
-		assertf( matches.size() <= 1, "%zd constructor/destructors found in %s", matches.size(), toString( stmt ).c_str() );
-		return matches.size() == 1 ? matches.front() : nullptr;
-	}
-
 	namespace {
-		DeclarationWithType * getCalledFunction( Expression * expr );
-
-		template<typename CallExpr>
-		DeclarationWithType * handleDerefCalledFunction( CallExpr * expr ) {
-			// (*f)(x) => should get "f"
-			std::string name = getFunctionName( expr );
-			assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
-			assertf( ! expr->get_args().empty(), "Cannot get called function from dereference with no arguments" );
-			return getCalledFunction( expr->get_args().front() );
-		}
-
-		DeclarationWithType * getCalledFunction( Expression * expr ) {
-			assert( expr );
-			if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
-				return varExpr->var;
-			} else if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) {
-				return memberExpr->member;
-			} else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
-				return getCalledFunction( castExpr->arg );
-			} else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( expr ) ) {
-				return handleDerefCalledFunction( untypedExpr );
-			} else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
-				return handleDerefCalledFunction( appExpr );
-			} else if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) {
-				return getCalledFunction( addrExpr->arg );
-			} else if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( expr ) ) {
-				return getCalledFunction( commaExpr->arg2 );
-			}
-			return nullptr;
-		}
-
-		DeclarationWithType * getFunctionCore( const Expression * expr ) {
-			if ( const auto * appExpr = dynamic_cast< const ApplicationExpr * >( expr ) ) {
-				return getCalledFunction( appExpr->function );
-			} else if ( const auto * untyped = dynamic_cast< const UntypedExpr * >( expr ) ) {
-				return getCalledFunction( untyped->function );
-			}
-			assertf( false, "getFunction with unknown expression: %s", toString( expr ).c_str() );
-		}
-	}
-
-	DeclarationWithType * getFunction( Expression * expr ) {
-		return getFunctionCore( expr );
-	}
-
-	const DeclarationWithType * getFunction( const Expression * expr ) {
-		return getFunctionCore( expr );
-	}
-
-	ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
-		ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
-		if ( ! appExpr ) return nullptr;
-		DeclarationWithType * function = getCalledFunction( appExpr->get_function() );
-		assertf( function, "getCalledFunction returned nullptr: %s", toString( appExpr->get_function() ).c_str() );
-		// check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
-		// will call all member dtors, and some members may have a user defined dtor.
-		return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : nullptr;
-	}
-
-	namespace {
-		template <typename Predicate>
-		bool allofCtorDtor( Statement * stmt, const Predicate & pred ) {
-			std::list< Expression * > callExprs;
-			collectCtorDtorCalls( stmt, callExprs );
-			return std::all_of( callExprs.begin(), callExprs.end(), pred);
-		}
-
 		template <typename Predicate>
 		bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) {
@@ -728,15 +337,4 @@
 			return std::all_of( callExprs.begin(), callExprs.end(), pred );
 		}
-	}
-
-	bool isIntrinsicSingleArgCallStmt( Statement * stmt ) {
-		return allofCtorDtor( stmt, []( Expression * callExpr ){
-			if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
-				FunctionType *funcType = GenPoly::getFunctionType( appExpr->function->result );
-				assert( funcType );
-				return funcType->get_parameters().size() == 1;
-			}
-			return false;
-		});
 	}
 
@@ -751,129 +349,4 @@
 			return false;
 		});
-	}
-
-	bool isIntrinsicCallStmt( Statement * stmt ) {
-		return allofCtorDtor( stmt, []( Expression * callExpr ) {
-			return isIntrinsicCallExpr( callExpr );
-		});
-	}
-
-	namespace {
-		template<typename CallExpr>
-		Expression *& callArg( CallExpr * callExpr, unsigned int pos ) {
-			if ( pos >= callExpr->get_args().size() ) assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.", pos, toString( callExpr ).c_str() );
-			for ( Expression *& arg : callExpr->get_args() ) {
-				if ( pos == 0 ) return arg;
-				pos--;
-			}
-			assert( false );
-		}
-	}
-
-	Expression *& getCallArg( Expression * callExpr, unsigned int pos ) {
-		if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr ) ) {
-			return callArg( appExpr, pos );
-		} else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( callExpr ) ) {
-			return callArg( untypedExpr, pos );
-		} else if ( TupleAssignExpr * tupleExpr = dynamic_cast< TupleAssignExpr * > ( callExpr ) ) {
-			std::list< Statement * > & stmts = tupleExpr->get_stmtExpr()->get_statements()->get_kids();
-			assertf( ! stmts.empty(), "TupleAssignExpr somehow has no statements." );
-			ExprStmt * stmt = strict_dynamic_cast< ExprStmt * >( stmts.back() );
-			TupleExpr * tuple = strict_dynamic_cast< TupleExpr * >( stmt->get_expr() );
-			assertf( ! tuple->get_exprs().empty(), "TupleAssignExpr somehow has empty tuple expr." );
-			return getCallArg( tuple->get_exprs().front(), pos );
-		} else if ( ImplicitCopyCtorExpr * copyCtor = dynamic_cast< ImplicitCopyCtorExpr * >( callExpr ) ) {
-			return getCallArg( copyCtor->callExpr, pos );
-		} else {
-			assertf( false, "Unexpected expression type passed to getCallArg: %s", toString( callExpr ).c_str() );
-		}
-	}
-
-	namespace {
-		std::string funcName( Expression * func );
-
-		template<typename CallExpr>
-		std::string handleDerefName( CallExpr * expr ) {
-			// (*f)(x) => should get name "f"
-			std::string name = getFunctionName( expr );
-			assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
-			assertf( ! expr->get_args().empty(), "Cannot get function name from dereference with no arguments" );
-			return funcName( expr->get_args().front() );
-		}
-
-		std::string funcName( Expression * func ) {
-			if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( func ) ) {
-				return nameExpr->get_name();
-			} else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( func ) ) {
-				return varExpr->get_var()->get_name();
-			} else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( func ) ) {
-				return funcName( castExpr->get_arg() );
-			} else if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( func ) ) {
-				return memberExpr->get_member()->get_name();
-			} else if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * > ( func ) ) {
-				return funcName( memberExpr->get_member() );
-			} else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( func ) ) {
-				return handleDerefName( untypedExpr );
-			} else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( func ) ) {
-				return handleDerefName( appExpr );
-			} else if ( ConstructorExpr * ctorExpr = dynamic_cast< ConstructorExpr * >( func ) ) {
-				return funcName( getCallArg( ctorExpr->get_callExpr(), 0 ) );
-			} else {
-				assertf( false, "Unexpected expression type being called as a function in call expression: %s", toString( func ).c_str() );
-			}
-		}
-	}
-
-	std::string getFunctionName( Expression * expr ) {
-		// there's some unforunate overlap here with getCalledFunction. Ideally this would be able to use getCalledFunction and
-		// return the name of the DeclarationWithType, but this needs to work for NameExpr and UntypedMemberExpr, where getCalledFunction
-		// can't possibly do anything reasonable.
-		if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) {
-			return funcName( appExpr->get_function() );
-		} else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * > ( expr ) ) {
-			return funcName( untypedExpr->get_function() );
-		} else {
-			std::cerr << expr << std::endl;
-			assertf( false, "Unexpected expression type passed to getFunctionName" );
-		}
-	}
-
-	Type * getPointerBase( Type * type ) {
-		if ( PointerType * ptrType = dynamic_cast< PointerType * >( type ) ) {
-			return ptrType->get_base();
-		} else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
-			return arrayType->get_base();
-		} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
-			return refType->get_base();
-		} else {
-			return nullptr;
-		}
-	}
-
-	Type * isPointerType( Type * type ) {
-		return getPointerBase( type ) ? type : nullptr;
-	}
-
-	ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src ) {
-		static FunctionDecl * assign = nullptr;
-		if ( ! assign ) {
-			// temporary? Generate a fake assignment operator to represent bitwise assignments.
-			// This operator could easily exist as a real function, but it's tricky because nothing should resolve to this function.
-			TypeDecl * td = new TypeDecl( "T", noStorageClasses, nullptr, TypeDecl::Dtype, true );
-			assign = new FunctionDecl( "?=?", noStorageClasses, LinkageSpec::Intrinsic, SymTab::genAssignType( new TypeInstType( noQualifiers, td->name, td ) ), nullptr );
-		}
-		if ( dynamic_cast< ReferenceType * >( dst->result ) ) {
-			for (int depth = dst->result->referenceDepth(); depth > 0; depth--) {
-				dst = new AddressExpr( dst );
-			}
-		} else {
-			dst = new CastExpr( dst, new ReferenceType( noQualifiers, dst->result->clone() ) );
-		}
-		if ( dynamic_cast< ReferenceType * >( src->result ) ) {
-			for (int depth = src->result->referenceDepth(); depth > 0; depth--) {
-				src = new AddressExpr( src );
-			}
-		}
-		return new ApplicationExpr( VariableExpr::functionPointer( assign ), { dst, src } );
 	}
 
@@ -908,45 +381,5 @@
 	}
 
-	struct ConstExprChecker : public WithShortCircuiting {
-		// most expressions are not const expr
-		void previsit( Expression * ) { isConstExpr = false; visit_children = false; }
-
-		void previsit( AddressExpr *addressExpr ) {
-			visit_children = false;
-
-			// address of a variable or member expression is constexpr
-			Expression * arg = addressExpr->get_arg();
-			if ( ! dynamic_cast< NameExpr * >( arg) && ! dynamic_cast< VariableExpr * >( arg ) && ! dynamic_cast< MemberExpr * >( arg ) && ! dynamic_cast< UntypedMemberExpr * >( arg ) ) isConstExpr = false;
-		}
-
-		// these expressions may be const expr, depending on their children
-		void previsit( SizeofExpr * ) {}
-		void previsit( AlignofExpr * ) {}
-		void previsit( UntypedOffsetofExpr * ) {}
-		void previsit( OffsetofExpr * ) {}
-		void previsit( OffsetPackExpr * ) {}
-		void previsit( CommaExpr * ) {}
-		void previsit( LogicalExpr * ) {}
-		void previsit( ConditionalExpr * ) {}
-		void previsit( CastExpr * ) {}
-		void previsit( ConstantExpr * ) {}
-
-		void previsit( VariableExpr * varExpr ) {
-			visit_children = false;
-
-			if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( varExpr->result ) ) {
-				long long int value;
-				if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
-					// enumerators are const expr
-					return;
-				}
-			}
-			isConstExpr = false;
-		}
-
-		bool isConstExpr = true;
-	};
-
-	struct ConstExprChecker_new : public ast::WithShortCircuiting {
+	struct ConstExprChecker : public ast::WithShortCircuiting {
 		// most expressions are not const expr
 		void previsit( const ast::Expr * ) { result = false; visit_children = false; }
@@ -991,26 +424,7 @@
 	};
 
-	bool isConstExpr( Expression * expr ) {
-		if ( expr ) {
-			PassVisitor<ConstExprChecker> checker;
-			expr->accept( checker );
-			return checker.pass.isConstExpr;
-		}
-		return true;
-	}
-
-	bool isConstExpr( Initializer * init ) {
-		if ( init ) {
-			PassVisitor<ConstExprChecker> checker;
-			init->accept( checker );
-			return checker.pass.isConstExpr;
-		} // if
-		// for all intents and purposes, no initializer means const expr
-		return true;
-	}
-
 	bool isConstExpr( const ast::Expr * expr ) {
 		if ( expr ) {
-			ast::Pass<ConstExprChecker_new> checker;
+			ast::Pass<ConstExprChecker> checker;
 			expr->accept( checker );
 			return checker.core.result;
@@ -1021,5 +435,5 @@
 	bool isConstExpr( const ast::Init * init ) {
 		if ( init ) {
-			ast::Pass<ConstExprChecker_new> checker;
+			ast::Pass<ConstExprChecker> checker;
 			init->accept( checker );
 			return checker.core.result;
@@ -1029,22 +443,4 @@
 	}
 
-	const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname ) {
-		const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( decl );
-		if ( ! function ) return nullptr;
-		if ( function->name != fname ) return nullptr;
-		FunctionType * ftype = function->type;
-		if ( ftype->parameters.size() != 2 ) return nullptr;
-
-		Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
-		Type * t2 = ftype->parameters.back()->get_type();
-		assert( t1 );
-
-		if ( ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, SymTab::Indexer() ) ) {
-			return function;
-		} else {
-			return nullptr;
-		}
-	}
-
 bool isAssignment( const ast::FunctionDecl * decl ) {
 	return CodeGen::isAssignment( decl->name ) && isCopyFunction( decl );
@@ -1073,28 +469,4 @@
 	return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2 );
 }
-
-
-	const FunctionDecl * isAssignment( const Declaration * decl ) {
-		return isCopyFunction( decl, "?=?" );
-	}
-	const FunctionDecl * isDestructor( const Declaration * decl ) {
-		if ( CodeGen::isDestructor( decl->name ) ) {
-			return dynamic_cast< const FunctionDecl * >( decl );
-		}
-		return nullptr;
-	}
-	const FunctionDecl * isDefaultConstructor( const Declaration * decl ) {
-		if ( CodeGen::isConstructor( decl->name ) ) {
-			if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) {
-				if ( func->type->parameters.size() == 1 ) {
-					return func;
-				}
-			}
-		}
-		return nullptr;
-	}
-	const FunctionDecl * isCopyConstructor( const Declaration * decl ) {
-		return isCopyFunction( decl, "?{}" );
-	}
 
 	#if defined( __x86_64 ) || defined( __i386 ) // assembler comment to prevent assembler warning message
@@ -1105,11 +477,4 @@
 	static const char * const data_section =  ".data" ASM_COMMENT;
 	static const char * const tlsd_section = ".tdata" ASM_COMMENT;
-	void addDataSectionAttribute( ObjectDecl * objDecl ) {
-		const bool is_tls = objDecl->get_storageClasses().is_threadlocal_any();
-		const char * section = is_tls ? tlsd_section : data_section;
-		objDecl->attributes.push_back(new Attribute("section", {
-			new ConstantExpr( Constant::from_string( section ) )
-		}));
-	}
 
 	void addDataSectionAttribute( ast::ObjectDecl * objDecl ) {
@@ -1121,3 +486,3 @@
 	}
 
-}
+} // namespace InitTweak
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/InitTweak/InitTweak.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -22,13 +22,7 @@
 
 #include "AST/Fwd.hpp"        // for AST nodes
-#include "SynTree/SynTree.h"  // for Visitor Nodes
 
 // helper functions for initialization
 namespace InitTweak {
-	const FunctionDecl * isAssignment( const Declaration * decl );
-	const FunctionDecl * isDestructor( const Declaration * decl );
-	const FunctionDecl * isDefaultConstructor( const Declaration * decl );
-	const FunctionDecl * isCopyConstructor( const Declaration * decl );
-	const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname );
 	bool isAssignment( const ast::FunctionDecl * decl );
 	bool isDestructor( const ast::FunctionDecl * decl );
@@ -38,76 +32,37 @@
 
 	/// returns the base type of the first parameter to a constructor/destructor/assignment function
-	Type * getTypeofThis( FunctionType * ftype );
 	const ast::Type * getTypeofThis( const ast::FunctionType * ftype );
 
 	/// returns the first parameter of a constructor/destructor/assignment function
-	ObjectDecl * getParamThis( FunctionType * ftype );
 	const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func);
 
 	/// generate a bitwise assignment operation.
-	ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src );
-
 	ast::Expr * createBitwiseAssignment( const ast::Expr * dst, const ast::Expr * src);
 
 	/// transform Initializer into an argument list that can be passed to a call expression
-	std::list< Expression * > makeInitList( Initializer * init );
 	std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init );
 
 	/// True if the resolver should try to construct dwt
-	bool tryConstruct( DeclarationWithType * dwt );
 	bool tryConstruct( const ast::DeclWithType * dwt );
 
 	/// True if the type can have a user-defined constructor
-	bool isConstructable( Type * t );
 	bool isConstructable( const ast::Type * t );
 
 	/// True if the Initializer contains designations
-	bool isDesignated( Initializer * init );
 	bool isDesignated( const ast::Init * init );
 
 	/// True if the ObjectDecl's Initializer nesting level is not deeper than the depth of its
 	/// type, where the depth of its type is the number of nested ArrayTypes + 1
-	bool checkInitDepth( ObjectDecl * objDecl );
 	bool checkInitDepth( const ast::ObjectDecl * objDecl );
-
-	/// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr)
-	DeclarationWithType * getFunction( Expression * expr );
-	const DeclarationWithType * getFunction( const Expression * expr );
-
-	/// Non-Null if expr is a call expression whose target function is intrinsic
-	ApplicationExpr * isIntrinsicCallExpr( Expression * expr );
 
 	/// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
 	/// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
 	/// Currently has assertions that make it less than fully general.
-	bool isIntrinsicSingleArgCallStmt( Statement * stmt );
 	bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt );
 
-	/// True if stmt is a call statement where the function called is intrinsic.
-	bool isIntrinsicCallStmt( Statement * stmt );
-
 	/// get all Ctor/Dtor call expressions from a Statement
-	void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
 	std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt );
 
-	/// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
-	Expression * getCtorDtorCall( Statement * stmt );
-
-	/// returns the name of the function being called
-	std::string getFunctionName( Expression * expr );
-
-	/// returns the argument to a call expression in position N indexed from 0
-	Expression *& getCallArg( Expression * callExpr, unsigned int pos );
-
-	/// returns the base type of a PointerType or ArrayType, else returns NULL
-	Type * getPointerBase( Type * );
-
-	/// returns the argument if it is a PointerType or ArrayType, else returns NULL
-	Type * isPointerType( Type * );
-
 	/// returns true if expr is trivially a compile-time constant
-	bool isConstExpr( Expression * expr );
-	bool isConstExpr( Initializer * init );
-
 	bool isConstExpr( const ast::Expr * expr );
 	bool isConstExpr( const ast::Init * init );
@@ -122,39 +77,7 @@
 	///    .section .data#,"a"
 	/// to avoid assembler warning "ignoring changed section attributes for .data"
-	void addDataSectionAttribute( ObjectDecl * objDecl );
-
 	void addDataSectionAttribute( ast::ObjectDecl * objDecl );
 
-	class InitExpander_old {
-	public:
-		// expand by stepping through init to get each list of arguments
-		InitExpander_old( Initializer * init );
-
-		// always expand to expr
-		InitExpander_old( Expression * expr );
-
-		// iterator-like interface
-		std::list< Expression * > operator*();
-		InitExpander_old & operator++();
-
-		// builds statement which has the same semantics as a C-style list initializer
-		// (for array initializers) using callExpr as the base expression to perform initialization
-		Statement * buildListInit( UntypedExpr * callExpr );
-		void addArrayIndex( Expression * index, Expression * dimension );
-		void clearArrayIndices();
-		bool addReference();
-
-		class ExpanderImpl;
-
-		typedef std::list< Expression * > IndexList;
-	private:
-		std::shared_ptr< ExpanderImpl > expander;
-		std::list< Expression * > cur;
-
-		// invariant: list of size 2N (elements come in pairs [index, dimension])
-		IndexList indices;
-	};
-
-	class InitExpander_new {
+	class InitExpander final {
 	public:
 		using IndexList = std::vector< ast::ptr< ast::Expr > >;
@@ -169,11 +92,11 @@
 	public:
 		/// Expand by stepping through init to get each list of arguments
-		InitExpander_new( const ast::Init * init );
+		InitExpander( const ast::Init * init );
 
 		/// Always expand to expression
-		InitExpander_new( const ast::Expr * expr );
+		InitExpander( const ast::Expr * expr );
 
 		std::vector< ast::ptr< ast::Expr > > operator* ();
-		InitExpander_new & operator++ ();
+		InitExpander & operator++ ();
 
 		/// builds statement which has the same semantics as a C-style list initializer (for array
@@ -188,5 +111,5 @@
 		bool addReference();
 	};
-} // namespace
+} // namespace InitTweak
 
 // Local Variables: //
Index: src/InitTweak/module.mk
===================================================================
--- src/InitTweak/module.mk	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/InitTweak/module.mk	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -24,5 +24,4 @@
 	InitTweak/FixGlobalInit.cc \
 	InitTweak/FixGlobalInit.h \
-	InitTweak/FixInit.cc \
 	InitTweak/FixInit.h \
 	InitTweak/FixInitNew.cpp
Index: c/MakeLibCfa.cc
===================================================================
--- src/MakeLibCfa.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,151 +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.
-//
-// MakeLibCfa.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sat May 16 10:33:33 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Feb 16 03:49:49 2020
-// Update Count     : 45
-//
-
-#include "MakeLibCfa.h"
-
-#include <cassert>                  // for assert
-#include <string>                   // for operator==, string
-
-#include "CodeGen/OperatorTable.h"  // for OperatorInfo, operatorLookup, Ope...
-#include "Common/PassVisitor.h"     // for PassVisitor
-#include "Common/SemanticError.h"   // for SemanticError
-#include "Common/UniqueName.h"      // for UniqueName
-#include "SynTree/LinkageSpec.h"    // for Spec, Intrinsic, C
-#include "SynTree/Declaration.h"    // for FunctionDecl, ObjectDecl, Declara...
-#include "SynTree/Expression.h"     // for NameExpr, UntypedExpr, VariableExpr
-#include "SynTree/Initializer.h"    // for SingleInit
-#include "SynTree/Label.h"          // for Label
-#include "SynTree/Statement.h"      // for CompoundStmt, ReturnStmt
-#include "SynTree/Type.h"           // for FunctionType
-#include "SynTree/Visitor.h"        // for acceptAll, Visitor
-
-namespace LibCfa {
-	namespace {
-		struct MakeLibCfa {
-		  public:
-			void postvisit( FunctionDecl* funcDecl );
-
-			std::list< Declaration* > newDecls;
-		};
-	}
-
-	void makeLibCfa( std::list< Declaration* > &prelude ) {
-		PassVisitor<MakeLibCfa> maker;
-		acceptAll( prelude, maker );
-		prelude.splice( prelude.end(), maker.pass.newDecls );
-	}
-
-	namespace {
-		struct TypeFinder	{
-			void postvisit( TypeInstType * inst ) {
-				// if a type variable is seen, assume all zero_t/one_t in the parameter list
-				//  can be replaced with the equivalent 'general' pointer.
-				if ( type ) return;
-				if ( inst->isFtype ) {
-					type = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), false ) );
-				} else {
-					type = new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) );
-				}
-			}
-			Type * type = nullptr;
-		};
-
-		struct ZeroOneReplacer {
-			ZeroOneReplacer( Type * t ) : type( t ) {}
-			~ZeroOneReplacer() { delete type; }
-			Type * type = nullptr;
-
-			Type * common( Type * t ) {
-				if ( ! type ) return t;
-				delete t;
-				return type->clone();
-			}
-
-			Type * postmutate( OneType * t ) { return common( t ); }
-			Type * postmutate( ZeroType * t ) { return common( t ); }
-		};
-
-		void fixZeroOneType( FunctionDecl * origFuncDecl ) {
-			// find appropriate type to replace zero_t/one_t with
-			PassVisitor<TypeFinder> finder;
-			origFuncDecl->type->accept( finder );
-			// replace zero_t/one_t in function type
-			PassVisitor<ZeroOneReplacer> replacer( finder.pass.type );
-			origFuncDecl->type->acceptMutator( replacer );
-		}
-
-		void MakeLibCfa::postvisit( FunctionDecl* origFuncDecl ) {
-			// don't change non-intrinsic functions
-			if ( origFuncDecl->get_linkage() != LinkageSpec::Intrinsic ) return;
-			// replace zero_t/one_t with void */void (*)(void)
-			fixZeroOneType( origFuncDecl );
-			// skip functions already defined
-			if ( origFuncDecl->get_statements() ) return;
-
-			FunctionDecl *funcDecl = origFuncDecl->clone();
-			const CodeGen::OperatorInfo * opInfo;
-			opInfo = CodeGen::operatorLookup( funcDecl->get_name() );
-			assert( opInfo );
-			assert( ! funcDecl->get_statements() );
-			// build a recursive call - this is okay, as the call will actually be codegen'd using operator syntax
-			UntypedExpr *newExpr = new UntypedExpr( new NameExpr( funcDecl->get_name() ) );
-			UniqueName paramNamer( "_p" );
-			std::list< DeclarationWithType* >::iterator param = funcDecl->get_functionType()->get_parameters().begin();
-			assert( param != funcDecl->get_functionType()->get_parameters().end() );
-
-			for ( ; param != funcDecl->get_functionType()->get_parameters().end(); ++param ) {
-				// name each unnamed parameter
-				if ( (*param)->get_name() == "" ) {
-					(*param)->set_name( paramNamer.newName() );
-					(*param)->set_linkage( LinkageSpec::C );
-				}
-				// add parameter to the expression
-				newExpr->get_args().push_back( new VariableExpr( *param ) );
-			} // for
-
-			funcDecl->set_statements( new CompoundStmt() );
-			newDecls.push_back( funcDecl );
-
-			Statement * stmt = nullptr;
-			switch ( opInfo->type ) {
-			  case CodeGen::OT_INDEX:
-			  case CodeGen::OT_CALL:
-			  case CodeGen::OT_PREFIX:
-			  case CodeGen::OT_POSTFIX:
-			  case CodeGen::OT_INFIX:
-			  case CodeGen::OT_PREFIXASSIGN:
-			  case CodeGen::OT_POSTFIXASSIGN:
-			  case CodeGen::OT_INFIXASSIGN:
-					// return the recursive call
-					stmt = new ReturnStmt( newExpr );
-					break;
-			  case CodeGen::OT_CTOR:
-			  case CodeGen::OT_DTOR:
-					// execute the recursive call
-					stmt = new ExprStmt( newExpr );
-					break;
-			  case CodeGen::OT_CONSTANT:
-			  case CodeGen::OT_LABELADDRESS:
-				// there are no intrinsic definitions of 0/1 or label addresses as functions
-				assert( false );
-			} // switch
-			funcDecl->get_statements()->push_back( stmt );
-		}
-	} // namespace
-} // namespace LibCfa
-
-// Local Variables: //
-// tab-width: 4 //
-// End: //
Index: src/MakeLibCfa.h
===================================================================
--- src/MakeLibCfa.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/MakeLibCfa.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -24,5 +24,4 @@
 
 namespace LibCfa {
-	void makeLibCfa( std::list< Declaration* > &prelude );
 	void makeLibCfa( ast::TranslationUnit & translationUnit );
 } // namespace LibCfa
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Makefile.am	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -22,5 +22,4 @@
       CompilationState.cc \
       CompilationState.h \
-      MakeLibCfa.cc \
 	  MakeLibCfaNew.cpp \
 	MakeLibCfa.h
@@ -42,5 +41,4 @@
 include AST/module.mk
 include CodeGen/module.mk
-include CodeTools/module.mk
 include Concurrency/module.mk
 include Common/module.mk
@@ -51,10 +49,9 @@
 include ResolvExpr/module.mk
 include SymTab/module.mk
-include SynTree/module.mk
 include Tuples/module.mk
 include Validate/module.mk
 include Virtual/module.mk
 
-$(addprefix $(srcdir)/, ResolvExpr/ConversionCost.cc ResolvExpr/CommonType.cc SymTab/ManglerCommon.cc) : $(srcdir)/SynTree/Type.h
+$(addprefix $(srcdir)/, ResolvExpr/ConversionCost.cc ResolvExpr/CommonType.cc SymTab/ManglerCommon.cc) : $(srcdir)/AST/Type.hpp
 
 $(srcdir)/AST/Type.hpp : BasicTypes-gen.cc
Index: src/Parser/RunParser.cpp
===================================================================
--- src/Parser/RunParser.cpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Parser/RunParser.cpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,7 +16,5 @@
 #include "RunParser.hpp"
 
-#include "AST/Convert.hpp"                  // for convert
 #include "AST/TranslationUnit.hpp"          // for TranslationUnit
-#include "CodeTools/TrackLoc.h"             // for fillLocations
 #include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
 #include "Parser/DeclarationNode.h"         // for DeclarationNode, buildList
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Parser/parser.yy	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -57,6 +57,4 @@
 #include "Common/SemanticError.h"						// error_str
 #include "Common/utility.h"								// for maybeMoveBuild, maybeBuild, CodeLo...
-
-#include "SynTree/Attribute.h"							// for Attribute
 
 // lex uses __null in a boolean context, it's fine.
Index: src/ResolvExpr/AdjustExprType.cc
===================================================================
--- src/ResolvExpr/AdjustExprType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/AdjustExprType.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -19,91 +19,14 @@
 #include "AST/Type.hpp"
 #include "AST/TypeEnvironment.hpp"
-#include "Common/PassVisitor.h"
-#include "SymTab/Indexer.h"       // for Indexer
-#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Kind::Ftype
-#include "SynTree/Mutator.h"      // for Mutator
-#include "SynTree/Type.h"         // for PointerType, TypeInstType, Type
-#include "TypeEnvironment.h"      // for EqvClass, TypeEnvironment
 
 namespace ResolvExpr {
 
 namespace {
-	class AdjustExprType_old final : public WithShortCircuiting {
-		public:
-		AdjustExprType_old( const TypeEnvironment & env, const SymTab::Indexer & indexer );
-		void premutate( VoidType * ) { visit_children = false; }
-		void premutate( BasicType * ) { visit_children = false; }
-		void premutate( PointerType * ) { visit_children = false; }
-		void premutate( ArrayType * ) { visit_children = false; }
-		void premutate( FunctionType * ) { visit_children = false; }
-		void premutate( StructInstType * ) { visit_children = false; }
-		void premutate( UnionInstType * ) { visit_children = false; }
-		void premutate( EnumInstType * ) { visit_children = false; }
-		void premutate( TraitInstType * ) { visit_children = false; }
-		void premutate( TypeInstType * ) { visit_children = false; }
-		void premutate( TupleType * ) { visit_children = false; }
-		void premutate( VarArgsType * ) { visit_children = false; }
-		void premutate( ZeroType * ) { visit_children = false; }
-		void premutate( OneType * ) { visit_children = false; }
-
-		Type * postmutate( ArrayType * arrayType );
-		Type * postmutate( FunctionType * functionType );
-		Type * postmutate( TypeInstType * aggregateUseType );
-
-		private:
-		const TypeEnvironment & env;
-		const SymTab::Indexer & indexer;
-	};
-
-	AdjustExprType_old::AdjustExprType_old( const TypeEnvironment &env, const SymTab::Indexer &indexer )
-		: env( env ), indexer( indexer ) {
-	}
-
-	Type * AdjustExprType_old::postmutate( ArrayType * arrayType ) {
-		PointerType * pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };
-		arrayType->base = nullptr;
-		delete arrayType;
-		return pointerType;
-	}
-
-	Type * AdjustExprType_old::postmutate( FunctionType * functionType ) {
-		return new PointerType{ Type::Qualifiers(), functionType };
-	}
-
-	Type * AdjustExprType_old::postmutate( TypeInstType * typeInst ) {
-		if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {
-			if ( eqvClass->data.kind == TypeDecl::Ftype ) {
-				return new PointerType{ Type::Qualifiers(), typeInst };
-			}
-		} else if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
-			if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl * >( ntDecl ) ) {
-				if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
-					return new PointerType{ Type::Qualifiers(), typeInst };
-				} // if
-			} // if
-		} // if
-		return typeInst;
-	}
-} // anonymous namespace
-
-void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
-	PassVisitor<AdjustExprType_old> adjuster( env, indexer );
-	Type * newType = type->acceptMutator( adjuster );
-	type = newType;
-}
-
-void adjustExprType( Type *& type ) {
-	TypeEnvironment env;
-	SymTab::Indexer indexer;
-	adjustExprType( type, env, indexer );
-}
-
-namespace {
-	class AdjustExprType_new final : public ast::WithShortCircuiting {
+	class AdjustExprType final : public ast::WithShortCircuiting {
 		const ast::SymbolTable & symtab;
 	public:
 		const ast::TypeEnvironment & tenv;
 
-		AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
+		AdjustExprType( const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
 		: symtab( syms ), tenv( e ) {}
 
@@ -152,5 +75,5 @@
 	const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab
 ) {
-	ast::Pass<AdjustExprType_new> adjuster{ env, symtab };
+	ast::Pass<AdjustExprType> adjuster{ env, symtab };
 	return type->accept( adjuster );
 }
Index: src/ResolvExpr/AdjustExprType.hpp
===================================================================
--- src/ResolvExpr/AdjustExprType.hpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/AdjustExprType.hpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,8 +16,4 @@
 #pragma once
 
-class Type;
-namespace SymTab {
-	class Indexer;
-}
 namespace ast {
 	class SymbolTable;
@@ -27,19 +23,4 @@
 
 namespace ResolvExpr {
-
-class TypeEnvironment;
-
-/// Replaces array types with the equivalent pointer, and function types with a pointer-to-function
-void adjustExprType( Type *& type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
-
-/// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer.
-void adjustExprType( Type *& type );
-
-template< typename ForwardIterator >
-void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer & indexer ) {
-	while ( begin != end ) {
-		adjustExprType( *begin++, env, indexer );
-	} // while
-}
 
 /// Replaces array types with equivalent pointer,
Index: c/ResolvExpr/Alternative.cc
===================================================================
--- src/ResolvExpr/Alternative.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,133 +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.
-//
-// Alternative.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sat May 16 23:44:23 2015
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Thu Oct 11 10:55:00 2018
-// Update Count     : 3
-//
-
-#include "Alternative.h"
-
-#include <ostream>                       // for operator<<, ostream, basic_o...
-#include <string>                        // for operator<<, char_traits, string
-#include <utility>                       // for move
-
-#include "Common/utility.h"              // for cloneAll
-#include "ResolvExpr/Cost.h"             // for Cost, Cost::zero, operator<<
-#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
-#include "SynTree/Expression.h"          // for Expression
-#include "SynTree/Type.h"                // for Type
-
-namespace ResolvExpr {
-	Alternative::Alternative() 
-	: cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ), env(), openVars(), need() {}
-
-	Alternative::Alternative( Expression *expr, const TypeEnvironment &env )
-	: cost( Cost::zero ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars(), need() {}
-	
-	Alternative::Alternative( const Alternative &o, Expression *expr, const Cost &cost ) 
-	: cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( o.env ), openVars( o.openVars ), 
-	  need() { cloneAll( o.need, need ); }
-
-	Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 
-		const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost )
-	: cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ), 
-	  need() { cloneAll( oneed, need ); }
-
-	Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 
-		const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost, 
-		const Cost &cvtCost )
-	: cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ), 
-	  need() { cloneAll( oneed, need ); }
-	
-	Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 
-		const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost)
-	: cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ), 
-	  need() { cloneAll( oneed, need ); }
-	
-	Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 
-		const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost, 
-		const Cost& cvtCost )
-	: cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ), 
-	  need() { cloneAll( oneed, need ); }
-	
-	Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 
-		AssertionSet &&needSet, const Cost &cost )
-	: cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( std::move(env) ), 
-	  openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {}
-	
-	Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 
-		AssertionSet &&needSet, const Cost &cost, const Cost &cvtCost )
-	: cost( cost ), cvtCost( cvtCost ), expr( expr ), env( std::move(env) ), 
-	  openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {}
-
-	Alternative::Alternative( const Alternative &other ) 
-	: cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), 
-	  env( other.env ), openVars( other.openVars ), need() { cloneAll( other.need, need ); }
-
-	Alternative &Alternative::operator=( const Alternative &other ) {
-		if ( &other == this ) return *this;
-		delete expr;
-		cost = other.cost;
-		cvtCost = other.cvtCost;
-		expr = maybeClone( other.expr );
-		env = other.env;
-		openVars = other.openVars;
-		need.clear();
-		cloneAll( other.need, need );
-		return *this;
-	}
-
-	Alternative::Alternative( Alternative && other ) 
-	: cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), 
-	  env( std::move( other.env ) ), openVars( std::move( other.openVars ) ), 
-	  need( std::move( other.need ) ) { other.expr = nullptr; }
-
-	Alternative & Alternative::operator=( Alternative && other ) {
-		if ( &other == this )  return *this;
-		delete expr;
-		cost = other.cost;
-		cvtCost = other.cvtCost;
-		expr = other.expr;
-		env = std::move( other.env );
-		openVars = std::move( other.openVars );
-		need = std::move( other.need );
-		other.expr = nullptr;
-		return *this;
-	}
-
-	Alternative::~Alternative() {
-		for ( AssertionItem& n : need ) { delete n.decl; }
-		delete expr;
-	}
-
-	void Alternative::print( std::ostream &os, Indenter indent ) const {
-		os << "Cost " << cost << ": ";
-		if ( expr ) {
-			expr->print( os, indent+1 );
-			os << std::endl << indent << "(types:" << std::endl;
-			os << indent+1;
-			expr->result->print( os, indent+1 );
-			os << std::endl << indent << ")" << std::endl;
-		} else {
-			os << "Null expression!" << std::endl;
-		} // if
-		os << indent << "Environment:";
-		env.print( os, indent+1 );
-		os << std::endl;
-	}
-
-} // namespace ResolvExpr
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ResolvExpr/Alternative.h
===================================================================
--- src/ResolvExpr/Alternative.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,124 +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.
-//
-// Alternative.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sat May 16 23:45:43 2015
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Thu Oct 11 10:55:00 2018
-// Update Count     : 4
-//
-
-#pragma once
-
-#include <iosfwd>             // for ostream
-#include <vector>             // for vector
-
-#include "Cost.h"             // for Cost
-#include "TypeEnvironment.h"  // for TypeEnvironment, AssertionSetValue
-
-#include "Common/utility.h"   // for maybeClone
-
-class Expression;
-
-namespace ResolvExpr {
-	/// One assertion to resolve
-	struct AssertionItem {
-		const DeclarationWithType* decl;
-		AssertionSetValue info;
-
-		AssertionItem() = default;
-		AssertionItem( const DeclarationWithType* decl, const AssertionSetValue& info )
-		: decl(decl), info(info) {}
-		AssertionItem( const AssertionSet::value_type& e ) : decl(e.first), info(e.second) {}
-		operator AssertionSet::value_type () const { return { decl, info }; }
-
-		// to support cloneAll
-		AssertionItem clone() const { return { maybeClone(decl), info }; }
-	};
-	/// A list of unresolved assertions
-	using AssertionList = std::vector<AssertionItem>;
-
-	/// Clones an assertion list into an assertion set
-	static inline void cloneAll( const AssertionList& src, AssertionSet& dst ) {
-		for ( const AssertionItem& item : src ) {
-			dst.emplace( maybeClone(item.decl), item.info );
-		}
-	}
-
-	/// Clones an assertion set into an assertion list
-	static inline void cloneAll( const AssertionSet& src, AssertionList& dst ) {
-		dst.reserve( dst.size() + src.size() );
-		for ( const auto& entry : src ) {
-			dst.emplace_back( maybeClone(entry.first), entry.second );
-		}
-	}
-
-	/// Clones an assertion list into an assertion list
-	static inline void cloneAll( const AssertionList& src, AssertionList& dst ) {
-		dst.reserve( dst.size() + src.size() );
-		for ( const AssertionItem& item : src ) {
-			dst.emplace_back( maybeClone(item.decl), item.info );
-		}
-	}
-
-	/// One option for resolution of an expression
-	struct Alternative {
-		Alternative();
-		Alternative( Expression *expr, const TypeEnvironment &env );
-		Alternative( const Alternative &o, Expression *expr, const Cost &cost );
-		Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars, 
-			const AssertionList& need, const Cost &cost );
-		Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars, 
-			const AssertionList& need, const Cost &cost, const Cost &cvtCost );
-		Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars, 
-			const AssertionSet &need, const Cost &cost);
-		Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars, 
-			const AssertionSet &need, const Cost &cost, const Cost& cvtCost );
-		Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 
-			AssertionSet &&need, const Cost &cost );
-		Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 
-			AssertionSet &&need, const Cost &cost, const Cost &cvtCost );
-		Alternative( const Alternative &other );
-		Alternative &operator=( const Alternative &other );
-		Alternative( Alternative && other );
-		Alternative &operator=( Alternative && other );
-		~Alternative();
-
-		void print( std::ostream &os, Indenter indent = {} ) const;
-
-		/// Returns the stored expression, but released from management of this Alternative
-		Expression* release_expr() {
-			Expression* tmp = expr;
-			expr = nullptr;
-			return tmp;
-		}
-
-		/// Sorts by cost
-		bool operator< ( const Alternative& o ) const { return cost < o.cost; }
-
-		Cost cost;            ///< Cost of the whole expression
-		Cost cvtCost;         ///< Cost of conversions to the satisfying expression
-		Expression *expr;     ///< Satisfying expression
-		TypeEnvironment env;  ///< Containing type environment
-		OpenVarSet openVars;  ///< Open variables for environment
-		AssertionList need;   ///< Assertions which need to be resolved
-	};
-
-	typedef std::vector< Alternative > AltList;
-
-	static inline std::ostream & operator<<(std::ostream & os, const ResolvExpr::Alternative & alt) {
-		alt.print( os );
-		return os;
-	}
-} // namespace ResolvExpr
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,1773 +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.
-//
-// AlternativeFinder.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sat May 16 23:52:08 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Thu Aug  8 16:35:00 2019
-// Update Count     : 38
-//
-
-#include "AlternativeFinder.h"
-
-#include <algorithm>               // for copy
-#include <cassert>                 // for strict_dynamic_cast, assert, assertf
-#include <cstddef>                 // for size_t
-#include <iostream>                // for operator<<, cerr, ostream, endl
-#include <iterator>                // for back_insert_iterator, back_inserter
-#include <list>                    // for _List_iterator, list, _List_const_...
-#include <map>                     // for _Rb_tree_iterator, map, _Rb_tree_c...
-#include <memory>                  // for allocator_traits<>::value_type, unique_ptr
-#include <utility>                 // for pair
-#include <vector>                  // for vector
-
-#include "CompilationState.h"      // for resolvep
-#include "AdjustExprType.hpp"      // for adjustExprType
-#include "Alternative.h"           // for AltList, Alternative
-#include "AST/Expr.hpp"
-#include "AST/SymbolTable.hpp"
-#include "AST/Type.hpp"
-#include "CastCost.hpp"            // for castCost
-#include "Common/SemanticError.h"  // for SemanticError
-#include "Common/utility.h"        // for deleteAll, printAll, CodeLocation
-#include "ConversionCost.h"        // for conversionCost
-#include "Cost.h"                  // for Cost, Cost::zero, operator<<, Cost...
-#include "ExplodedActual.h"        // for ExplodedActual
-#include "InitTweak/InitTweak.h"   // for getFunctionName
-#include "PolyCost.hpp"            // for polyCost
-#include "RenameVars.h"            // for RenameVars, global_renamer
-#include "ResolveAssertions.h"     // for resolveAssertions
-#include "ResolveTypeof.h"         // for resolveTypeof
-#include "Resolver.h"              // for resolveStmtExpr
-#include "SpecCost.hpp"            // for specCost
-#include "SymTab/Indexer.h"        // for Indexer
-#include "SymTab/Mangler.h"        // for Mangler
-#include "SymTab/ValidateType.h"   // for validateType
-#include "SynTree/Constant.h"      // for Constant
-#include "SynTree/Declaration.h"   // for DeclarationWithType, TypeDecl, Dec...
-#include "SynTree/Expression.h"    // for Expression, CastExpr, NameExpr
-#include "SynTree/Initializer.h"   // for SingleInit, operator<<, Designation
-#include "SynTree/SynTree.h"       // for UniqueId
-#include "SynTree/Type.h"          // for Type, FunctionType, PointerType
-#include "Tuples/Explode.h"        // for explode
-#include "Tuples/Tuples.h"         // for isTtype, handleTupleAssignment
-#include "typeops.h"               // for combos
-#include "Unify.h"                 // for unify
-
-#define PRINT( text ) if ( resolvep ) { text }
-//#define DEBUG_COST
-
-namespace ResolvExpr {
-	struct AlternativeFinder::Finder : public WithShortCircuiting {
-		Finder( AlternativeFinder & altFinder ) : altFinder( altFinder ), indexer( altFinder.indexer ), alternatives( altFinder.alternatives ), env( altFinder.env ), targetType( altFinder.targetType )  {}
-
-		void previsit( BaseSyntaxNode * ) { visit_children = false; }
-
-		void postvisit( ApplicationExpr * applicationExpr );
-		void postvisit( UntypedExpr * untypedExpr );
-		void postvisit( AddressExpr * addressExpr );
-		void postvisit( LabelAddressExpr * labelExpr );
-		void postvisit( CastExpr * castExpr );
-		void postvisit( VirtualCastExpr * castExpr );
-		void postvisit( KeywordCastExpr * castExpr );
-		void postvisit( UntypedMemberExpr * memberExpr );
-		void postvisit( MemberExpr * memberExpr );
-		void postvisit( NameExpr * variableExpr );
-		void postvisit( VariableExpr * variableExpr );
-		void postvisit( ConstantExpr * constantExpr );
-		void postvisit( SizeofExpr * sizeofExpr );
-		void postvisit( AlignofExpr * alignofExpr );
-		void postvisit( UntypedOffsetofExpr * offsetofExpr );
-		void postvisit( OffsetofExpr * offsetofExpr );
-		void postvisit( OffsetPackExpr * offsetPackExpr );
-		void postvisit( LogicalExpr * logicalExpr );
-		void postvisit( ConditionalExpr * conditionalExpr );
-		void postvisit( CommaExpr * commaExpr );
-		void postvisit( ImplicitCopyCtorExpr  * impCpCtorExpr );
-		void postvisit( ConstructorExpr  * ctorExpr );
-		void postvisit( RangeExpr  * rangeExpr );
-		void postvisit( UntypedTupleExpr * tupleExpr );
-		void postvisit( TupleExpr * tupleExpr );
-		void postvisit( TupleIndexExpr * tupleExpr );
-		void postvisit( TupleAssignExpr * tupleExpr );
-		void postvisit( UniqueExpr * unqExpr );
-		void postvisit( StmtExpr * stmtExpr );
-		void postvisit( UntypedInitExpr * initExpr );
-		void postvisit( InitExpr * initExpr );
-		void postvisit( DeletedExpr * delExpr );
-		void postvisit( GenericExpr * genExpr );
-
-		/// Adds alternatives for anonymous members
-		void addAnonConversions( const Alternative & alt );
-		/// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
-		template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name );
-		/// Adds alternatives for member expressions where the left side has tuple type
-		void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member );
-		/// Adds alternatives for offsetof expressions, given the base type and name of the member
-		template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
-		/// Takes a final result and checks if its assertions can be satisfied
-		template<typename OutputIterator>
-		void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out );
-		/// Finds matching alternatives for a function, given a set of arguments
-		template<typename OutputIterator>
-		void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs_old& args, OutputIterator out );
-		/// Sets up parameter inference for an output alternative
-		template< typename OutputIterator >
-		void inferParameters( Alternative &newAlt, OutputIterator out );
-	private:
-		AlternativeFinder & altFinder;
-		const SymTab::Indexer &indexer;
-		AltList & alternatives;
-		const TypeEnvironment &env;
-		Type *& targetType;
-	};
-
-	Cost sumCost( const AltList &in ) {
-		Cost total = Cost::zero;
-		for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
-			total += i->cost;
-		}
-		return total;
-	}
-
-	void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt ) {
-		std::vector<std::string> sorted;
-		sorted.reserve(list.size());
-		for(const auto & c : list) {
-			std::stringstream ss;
-			c.print( ss, indentAmt );
-			sorted.push_back(ss.str());
-		}
-
-		std::sort(sorted.begin(), sorted.end());
-
-		for ( const auto & s : sorted ) {
-			os << s << std::endl;
-		}
-	}
-
-	namespace {
-		void makeExprList( const AltList &in, std::list< Expression* > &out ) {
-			for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
-				out.push_back( i->expr->clone() );
-			}
-		}
-
-		struct PruneStruct {
-			bool isAmbiguous;
-			AltList::iterator candidate;
-			PruneStruct() {}
-			PruneStruct( AltList::iterator candidate ): isAmbiguous( false ), candidate( candidate ) {}
-		};
-
-		/// Prunes a list of alternatives down to those that have the minimum conversion cost for a given return type; skips ambiguous interpretations
-		template< typename InputIterator, typename OutputIterator >
-		void pruneAlternatives( InputIterator begin, InputIterator end, OutputIterator out ) {
-			// select the alternatives that have the minimum conversion cost for a particular set of result types
-			std::map< std::string, PruneStruct > selected;
-			for ( AltList::iterator candidate = begin; candidate != end; ++candidate ) {
-				PruneStruct current( candidate );
-				std::string mangleName;
-				{
-					Type * newType = candidate->expr->get_result()->clone();
-					candidate->env.apply( newType );
-					mangleName = SymTab::Mangler::mangle( newType );
-					delete newType;
-				}
-				std::map< std::string, PruneStruct >::iterator mapPlace = selected.find( mangleName );
-				if ( mapPlace != selected.end() ) {
-					if ( candidate->cost < mapPlace->second.candidate->cost ) {
-						PRINT(
-							std::cerr << "cost " << candidate->cost << " beats " << mapPlace->second.candidate->cost << std::endl;
-						)
-						selected[ mangleName ] = current;
-					} else if ( candidate->cost == mapPlace->second.candidate->cost ) {
-						// if one of the candidates contains a deleted identifier, can pick the other, since
-						// deleted expressions should not be ambiguous if there is another option that is at least as good
-						if ( findDeletedExpr( candidate->expr ) ) {
-							// do nothing
-							PRINT( std::cerr << "candidate is deleted" << std::endl; )
-						} else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) {
-							PRINT( std::cerr << "current is deleted" << std::endl; )
-							selected[ mangleName ] = current;
-						} else {
-							PRINT(
-								std::cerr << "marking ambiguous" << std::endl;
-							)
-							mapPlace->second.isAmbiguous = true;
-						}
-					} else {
-						PRINT(
-							std::cerr << "cost " << candidate->cost << " loses to " << mapPlace->second.candidate->cost << std::endl;
-						)
-					}
-				} else {
-					selected[ mangleName ] = current;
-				}
-			}
-
-			// accept the alternatives that were unambiguous
-			for ( std::map< std::string, PruneStruct >::iterator target = selected.begin(); target != selected.end(); ++target ) {
-				if ( ! target->second.isAmbiguous ) {
-					Alternative &alt = *target->second.candidate;
-					alt.env.applyFree( alt.expr->get_result() );
-					*out++ = alt;
-				}
-			}
-		}
-
-		void renameTypes( Expression *expr ) {
-			renameTyVars( expr->result );
-		}
-	} // namespace
-
-	void referenceToRvalueConversion( Expression *& expr, Cost & cost ) {
-		if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
-			// cast away reference from expr
-			expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
-			cost.incReference();
-		}
-	}
-
-	template< typename InputIterator, typename OutputIterator >
-	void AlternativeFinder::findSubExprs( InputIterator begin, InputIterator end, OutputIterator out ) {
-		while ( begin != end ) {
-			AlternativeFinder finder( indexer, env );
-			finder.findWithAdjustment( *begin );
-			// XXX  either this
-			//Designators::fixDesignations( finder, (*begin++)->get_argName() );
-			// or XXX this
-			begin++;
-			PRINT(
-				std::cerr << "findSubExprs" << std::endl;
-				printAlts( finder.alternatives, std::cerr );
-			)
-			*out++ = finder;
-		}
-	}
-
-	AlternativeFinder::AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env )
-		: indexer( indexer ), env( env ) {
-	}
-
-	void AlternativeFinder::find( Expression *expr, ResolvMode mode ) {
-		PassVisitor<Finder> finder( *this );
-		expr->accept( finder );
-		if ( mode.failFast && alternatives.empty() ) {
-			PRINT(
-				std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
-			)
-			SemanticError( expr, "No reasonable alternatives for expression " );
-		}
-		if ( mode.prune ) {
-			// trim candidates just to those where the assertions resolve
-			// - necessary pre-requisite to pruning
-			AltList candidates;
-			std::list<std::string> errors;
-			for ( unsigned i = 0; i < alternatives.size(); ++i ) {
-				resolveAssertions( alternatives[i], indexer, candidates, errors );
-			}
-			// fail early if none such
-			if ( mode.failFast && candidates.empty() ) {
-				std::ostringstream stream;
-				stream << "No alternatives with satisfiable assertions for " << expr << "\n";
-				//        << "Alternatives with failing assertions are:\n";
-				// printAlts( alternatives, stream, 1 );
-				for ( const auto& err : errors ) {
-					stream << err;
-				}
-				SemanticError( expr->location, stream.str() );
-			}
-			// reset alternatives
-			alternatives = std::move( candidates );
-		}
-		if ( mode.prune ) {
-			auto oldsize = alternatives.size();
-			PRINT(
-				std::cerr << "alternatives before prune:" << std::endl;
-				printAlts( alternatives, std::cerr );
-			)
-			AltList pruned;
-			pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) );
-			if ( mode.failFast && pruned.empty() ) {
-				std::ostringstream stream;
-				AltList winners;
-				findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
-				stream << "Cannot choose between " << winners.size() << " alternatives for expression\n";
-				expr->print( stream );
-				stream << " Alternatives are:\n";
-				printAlts( winners, stream, 1 );
-				SemanticError( expr->location, stream.str() );
-			}
-			alternatives = std::move(pruned);
-			PRINT(
-				std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl;
-			)
-			PRINT(
-				std::cerr << "there are " << alternatives.size() << " alternatives after elimination" << std::endl;
-			)
-		}
-		// adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted
-		if ( mode.adjust ) {
-			for ( Alternative& i : alternatives ) {
-				adjustExprType( i.expr->get_result(), i.env, indexer );
-			}
-		}
-
-		// Central location to handle gcc extension keyword, etc. for all expression types.
-		for ( Alternative &iter: alternatives ) {
-			iter.expr->set_extension( expr->get_extension() );
-			iter.expr->location = expr->location;
-		} // for
-	}
-
-	void AlternativeFinder::findWithAdjustment( Expression *expr ) {
-		find( expr, ResolvMode::withAdjustment() );
-	}
-
-	void AlternativeFinder::findWithoutPrune( Expression * expr ) {
-		find( expr, ResolvMode::withoutPrune() );
-	}
-
-	void AlternativeFinder::maybeFind( Expression * expr ) {
-		find( expr, ResolvMode::withoutFailFast() );
-	}
-
-	void AlternativeFinder::Finder::addAnonConversions( const Alternative & alt ) {
-		// adds anonymous member interpretations whenever an aggregate value type is seen.
-		// it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
-		std::unique_ptr<Expression> aggrExpr( alt.expr->clone() );
-		alt.env.apply( aggrExpr->result );
-		Type * aggrType = aggrExpr->result;
-		if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
-			aggrType = aggrType->stripReferences();
-			aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) );
-		}
-
-		if ( StructInstType * structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
-			addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
-		} else if ( UnionInstType * unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
-			addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
-		} // if
-	}
-
-	template< typename StructOrUnionType >
-	void AlternativeFinder::Finder::addAggMembers( StructOrUnionType * aggInst, Expression * expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {
-		std::list< Declaration* > members;
-		aggInst->lookup( name, members );
-
-		for ( Declaration * decl : members ) {
-			if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
-				// addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
-				// can't construct in place and use vector::back
-				Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost };
-				renameTypes( newAlt.expr );
-				addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
-				alternatives.push_back( std::move(newAlt) );
-			} else {
-				assert( false );
-			}
-		}
-	}
-
-	void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression * expr, const Alternative &alt, const Cost &newCost, Expression * member ) {
-		if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
-			// get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
-			auto val = constantExpr->intValue();
-			std::string tmp;
-			if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
-				alternatives.push_back( Alternative{
-					alt, new TupleIndexExpr( expr->clone(), val ), newCost } );
-			} // if
-		} // if
-	}
-
-	void AlternativeFinder::Finder::postvisit( ApplicationExpr * applicationExpr ) {
-		alternatives.push_back( Alternative{ applicationExpr->clone(), env } );
-	}
-
-	Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue,
-			const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
-		PRINT(
-			std::cerr << std::endl << "converting ";
-			actualType->print( std::cerr, 8 );
-			std::cerr << std::endl << " to ";
-			formalType->print( std::cerr, 8 );
-			std::cerr << std::endl << "environment is: ";
-			env.print( std::cerr, 8 );
-			std::cerr << std::endl;
-		)
-		Cost convCost = conversionCost( actualType, formalType, actualIsLvalue, indexer, env );
-		PRINT(
-			std::cerr << std::endl << "cost is " << convCost << std::endl;
-		)
-		if ( convCost == Cost::infinity ) {
-			return convCost;
-		}
-		convCost.incPoly( polyCost( formalType, env, indexer ) + polyCost( actualType, env, indexer ) );
-		PRINT(
-			std::cerr << "cost with polycost is " << convCost << std::endl;
-		)
-		return convCost;
-	}
-
-	Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
-		Cost convCost = computeConversionCost(
-			actualExpr->result, formalType, actualExpr->get_lvalue(), indexer, env );
-
-		// if there is a non-zero conversion cost, ignoring poly cost, then the expression requires conversion.
-		// ignore poly cost for now, since this requires resolution of the cast to infer parameters and this
-		// does not currently work for the reason stated below.
-		Cost tmpCost = convCost;
-		tmpCost.incPoly( -tmpCost.get_polyCost() );
-		if ( tmpCost != Cost::zero ) {
-			Type *newType = formalType->clone();
-			env.apply( newType );
-			actualExpr = new CastExpr( actualExpr, newType );
-			// xxx - SHOULD be able to resolve this cast, but at the moment pointers are not castable to zero_t, but are implicitly convertible. This is clearly
-			// inconsistent, once this is fixed it should be possible to resolve the cast.
-			// xxx - this isn't working, it appears because type1 (the formal type) is seen as widenable, but it shouldn't be, because this makes the conversion from DT* to DT* since commontype(zero_t, DT*) is DT*, rather than just nothing.
-
-			// AlternativeFinder finder( indexer, env );
-			// finder.findWithAdjustment( actualExpr );
-			// assertf( finder.get_alternatives().size() > 0, "Somehow castable expression failed to find alternatives." );
-			// assertf( finder.get_alternatives().size() == 1, "Somehow got multiple alternatives for known cast expression." );
-			// Alternative & alt = finder.get_alternatives().front();
-			// delete actualExpr;
-			// actualExpr = alt.expr->clone();
-		}
-		return convCost;
-	}
-
-	Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
-		ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr );
-		PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
-		FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
-
-		Cost convCost = Cost::zero;
-		std::list< DeclarationWithType* >& formals = function->parameters;
-		std::list< DeclarationWithType* >::iterator formal = formals.begin();
-		std::list< Expression* >& actuals = appExpr->args;
-
-		for ( Expression*& actualExpr : actuals ) {
-			Type * actualType = actualExpr->result;
-			PRINT(
-				std::cerr << "actual expression:" << std::endl;
-				actualExpr->print( std::cerr, 8 );
-				std::cerr << "--- results are" << std::endl;
-				actualType->print( std::cerr, 8 );
-			)
-			if ( formal == formals.end() ) {
-				if ( function->isVarArgs ) {
-					convCost.incUnsafe();
-					PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
-					// convert reference-typed expressions to value-typed expressions
-					referenceToRvalueConversion( actualExpr, convCost );
-					continue;
-				} else {
-					return Cost::infinity;
-				}
-			}
-			if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) {
-				// default arguments should be free - don't include conversion cost.
-				// Unwrap them here because they are not relevant to the rest of the system.
-				actualExpr = def->expr;
-				++formal;
-				continue;
-			}
-			// mark conversion cost to formal and also specialization cost of formal type
-			Type * formalType = (*formal)->get_type();
-			convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env );
-			convCost.decSpec( specCost( formalType ) );
-			++formal; // can't be in for-loop update because of the continue
-		}
-		if ( formal != formals.end() ) {
-			return Cost::infinity;
-		}
-
-		// specialization cost of return types can't be accounted for directly, it disables
-		// otherwise-identical calls, like this example based on auto-newline in the I/O lib:
-		//
-		//   forall(otype OS) {
-		//     void ?|?(OS&, int);  // with newline
-		//     OS&  ?|?(OS&, int);  // no newline, always chosen due to more specialization
-		//   }
-
-		// mark type variable and specialization cost of forall clause
-		convCost.incVar( function->forall.size() );
-		for ( TypeDecl* td : function->forall ) {
-			convCost.decSpec( td->assertions.size() );
-		}
-
-		return convCost;
-	}
-
-	/// Adds type variables to the open variable set and marks their assertions
-	void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions ) {
-		for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
-			unifiableVars[ (*tyvar)->get_name() ] = TypeDecl::Data{ *tyvar };
-			for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->assertions.begin(); assert != (*tyvar)->assertions.end(); ++assert ) {
-				needAssertions[ *assert ].isUsed = true;
-			}
-		}
-	}
-
-	/// Unique identifier for matching expression resolutions to their requesting expression (located in CandidateFinder.cpp)
-	extern UniqueId globalResnSlot;
-
-	template< typename OutputIterator >
-	void AlternativeFinder::Finder::inferParameters( Alternative &newAlt, OutputIterator out ) {
-		// Set need bindings for any unbound assertions
-		UniqueId crntResnSlot = 0;  // matching ID for this expression's assertions
-		for ( auto& assn : newAlt.need ) {
-			// skip already-matched assertions
-			if ( assn.info.resnSlot != 0 ) continue;
-			// assign slot for expression if needed
-			if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }
-			// fix slot to assertion
-			assn.info.resnSlot = crntResnSlot;
-		}
-		// pair slot to expression
-		if ( crntResnSlot != 0 ) { newAlt.expr->resnSlots.push_back( crntResnSlot ); }
-
-		// add to output list, assertion resolution is deferred
-		*out++ = newAlt;
-	}
-
-	/// Gets a default value from an initializer, nullptr if not present
-	ConstantExpr* getDefaultValue( Initializer* init ) {
-		if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) {
-			if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) {
-				return dynamic_cast<ConstantExpr*>( ce->arg );
-			} else {
-				return dynamic_cast<ConstantExpr*>( si->value );
-			}
-		}
-		return nullptr;
-	}
-
-	/// State to iteratively build a match of parameter expressions to arguments
-	struct ArgPack {
-		std::size_t parent;                ///< Index of parent pack
-		std::unique_ptr<Expression> expr;  ///< The argument stored here
-		Cost cost;                         ///< The cost of this argument
-		TypeEnvironment env;               ///< Environment for this pack
-		AssertionSet need;                 ///< Assertions outstanding for this pack
-		AssertionSet have;                 ///< Assertions found for this pack
-		OpenVarSet openVars;               ///< Open variables for this pack
-		unsigned nextArg;                  ///< Index of next argument in arguments list
-		unsigned tupleStart;               ///< Number of tuples that start at this index
-		unsigned nextExpl;                 ///< Index of next exploded element
-		unsigned explAlt;                  ///< Index of alternative for nextExpl > 0
-
-		ArgPack()
-			: parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0),
-			  tupleStart(0), nextExpl(0), explAlt(0) {}
-
-		ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have,
-				const OpenVarSet& openVars)
-			: parent(0), expr(), cost(Cost::zero), env(env), need(need), have(have),
-			  openVars(openVars), nextArg(0), tupleStart(0), nextExpl(0), explAlt(0) {}
-
-		ArgPack(std::size_t parent, Expression* expr, TypeEnvironment&& env, AssertionSet&& need,
-				AssertionSet&& have, OpenVarSet&& openVars, unsigned nextArg,
-				unsigned tupleStart = 0, Cost cost = Cost::zero, unsigned nextExpl = 0,
-				unsigned explAlt = 0 )
-			: parent(parent), expr(expr->clone()), cost(cost), env(std::move(env)), need(std::move(need)),
-			  have(std::move(have)), openVars(std::move(openVars)), nextArg(nextArg), tupleStart(tupleStart),
-			  nextExpl(nextExpl), explAlt(explAlt) {}
-
-		ArgPack(const ArgPack& o, TypeEnvironment&& env, AssertionSet&& need, AssertionSet&& have,
-				OpenVarSet&& openVars, unsigned nextArg, Cost added )
-			: parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), cost(o.cost + added),
-			  env(std::move(env)), need(std::move(need)), have(std::move(have)), openVars(std::move(openVars)),
-			  nextArg(nextArg), tupleStart(o.tupleStart), nextExpl(0), explAlt(0) {}
-
-		/// true iff this pack is in the middle of an exploded argument
-		bool hasExpl() const { return nextExpl > 0; }
-
-		/// Gets the list of exploded alternatives for this pack
-		const ExplodedActual& getExpl( const ExplodedArgs_old& args ) const {
-			return args[nextArg-1][explAlt];
-		}
-
-		/// Ends a tuple expression, consolidating the appropriate actuals
-		void endTuple( const std::vector<ArgPack>& packs ) {
-			// add all expressions in tuple to list, summing cost
-			std::list<Expression*> exprs;
-			const ArgPack* pack = this;
-			if ( expr ) { exprs.push_front( expr.release() ); }
-			while ( pack->tupleStart == 0 ) {
-				pack = &packs[pack->parent];
-				exprs.push_front( pack->expr->clone() );
-				cost += pack->cost;
-			}
-			// reset pack to appropriate tuple
-			expr.reset( new TupleExpr( exprs ) );
-			tupleStart = pack->tupleStart - 1;
-			parent = pack->parent;
-		}
-	};
-
-	/// Instantiates an argument to match a formal, returns false if no results left
-	bool instantiateArgument( Type* formalType, Initializer* initializer,
-			const ExplodedArgs_old& args, std::vector<ArgPack>& results, std::size_t& genStart,
-			const SymTab::Indexer& indexer, unsigned nTuples = 0 ) {
-		if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {
-			// formalType is a TupleType - group actuals into a TupleExpr
-			++nTuples;
-			for ( Type* type : *tupleType ) {
-				// xxx - dropping initializer changes behaviour from previous, but seems correct
-				// ^^^ need to handle the case where a tuple has a default argument
-				if ( ! instantiateArgument(
-						type, nullptr, args, results, genStart, indexer, nTuples ) )
-					return false;
-				nTuples = 0;
-			}
-			// re-consititute tuples for final generation
-			for ( auto i = genStart; i < results.size(); ++i ) {
-				results[i].endTuple( results );
-			}
-			return true;
-		} else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) {
-			// formalType is a ttype, consumes all remaining arguments
-			// xxx - mixing default arguments with variadic??
-
-			// completed tuples; will be spliced to end of results to finish
-			std::vector<ArgPack> finalResults{};
-
-			// iterate until all results completed
-			std::size_t genEnd;
-			++nTuples;
-			do {
-				genEnd = results.size();
-
-				// add another argument to results
-				for ( std::size_t i = genStart; i < genEnd; ++i ) {
-					auto nextArg = results[i].nextArg;
-
-					// use next element of exploded tuple if present
-					if ( results[i].hasExpl() ) {
-						const ExplodedActual& expl = results[i].getExpl( args );
-
-						unsigned nextExpl = results[i].nextExpl + 1;
-						if ( nextExpl == expl.exprs.size() ) {
-							nextExpl = 0;
-						}
-
-						results.emplace_back(
-							i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env),
-							copy(results[i].need), copy(results[i].have),
-							copy(results[i].openVars), nextArg, nTuples, Cost::zero, nextExpl,
-							results[i].explAlt );
-
-						continue;
-					}
-
-					// finish result when out of arguments
-					if ( nextArg >= args.size() ) {
-						ArgPack newResult{
-							results[i].env, results[i].need, results[i].have,
-							results[i].openVars };
-						newResult.nextArg = nextArg;
-						Type* argType;
-
-						if ( nTuples > 0 || ! results[i].expr ) {
-							// first iteration or no expression to clone,
-							// push empty tuple expression
-							newResult.parent = i;
-							std::list<Expression*> emptyList;
-							newResult.expr.reset( new TupleExpr( emptyList ) );
-							argType = newResult.expr->get_result();
-						} else {
-							// clone result to collect tuple
-							newResult.parent = results[i].parent;
-							newResult.cost = results[i].cost;
-							newResult.tupleStart = results[i].tupleStart;
-							newResult.expr.reset( results[i].expr->clone() );
-							argType = newResult.expr->get_result();
-
-							if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) {
-								// the case where a ttype value is passed directly is special,
-								// e.g. for argument forwarding purposes
-								// xxx - what if passing multiple arguments, last of which is
-								//       ttype?
-								// xxx - what would happen if unify was changed so that unifying
-								//       tuple
-								// types flattened both before unifying lists? then pass in
-								// TupleType (ttype) below.
-								--newResult.tupleStart;
-							} else {
-								// collapse leftover arguments into tuple
-								newResult.endTuple( results );
-								argType = newResult.expr->get_result();
-							}
-						}
-
-						// check unification for ttype before adding to final
-						if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have,
-								newResult.openVars, indexer ) ) {
-							finalResults.push_back( std::move(newResult) );
-						}
-
-						continue;
-					}
-
-					// add each possible next argument
-					for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {
-						const ExplodedActual& expl = args[nextArg][j];
-
-						// fresh copies of parent parameters for this iteration
-						TypeEnvironment env = results[i].env;
-						OpenVarSet openVars = results[i].openVars;
-
-						env.addActual( expl.env, openVars );
-
-						// skip empty tuple arguments by (near-)cloning parent into next gen
-						if ( expl.exprs.empty() ) {
-							results.emplace_back(
-								results[i], std::move(env), copy(results[i].need),
-								copy(results[i].have), std::move(openVars), nextArg + 1, expl.cost );
-
-							continue;
-						}
-
-						// add new result
-						results.emplace_back(
-							i, expl.exprs.front().get(), std::move(env), copy(results[i].need),
-							copy(results[i].have), std::move(openVars), nextArg + 1,
-							nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
-					}
-				}
-
-				// reset for next round
-				genStart = genEnd;
-				nTuples = 0;
-			} while ( genEnd != results.size() );
-
-			// splice final results onto results
-			for ( std::size_t i = 0; i < finalResults.size(); ++i ) {
-				results.push_back( std::move(finalResults[i]) );
-			}
-			return ! finalResults.empty();
-		}
-
-		// iterate each current subresult
-		std::size_t genEnd = results.size();
-		for ( std::size_t i = genStart; i < genEnd; ++i ) {
-			auto nextArg = results[i].nextArg;
-
-			// use remainder of exploded tuple if present
-			if ( results[i].hasExpl() ) {
-				const ExplodedActual& expl = results[i].getExpl( args );
-				Expression* expr = expl.exprs[results[i].nextExpl].get();
-
-				TypeEnvironment env = results[i].env;
-				AssertionSet need = results[i].need, have = results[i].have;
-				OpenVarSet openVars = results[i].openVars;
-
-				Type* actualType = expr->get_result();
-
-				PRINT(
-					std::cerr << "formal type is ";
-					formalType->print( std::cerr );
-					std::cerr << std::endl << "actual type is ";
-					actualType->print( std::cerr );
-					std::cerr << std::endl;
-				)
-
-				if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) {
-					unsigned nextExpl = results[i].nextExpl + 1;
-					if ( nextExpl == expl.exprs.size() ) {
-						nextExpl = 0;
-					}
-
-					results.emplace_back(
-						i, expr, std::move(env), std::move(need), std::move(have), std::move(openVars), nextArg,
-						nTuples, Cost::zero, nextExpl, results[i].explAlt );
-				}
-
-				continue;
-			}
-
-			// use default initializers if out of arguments
-			if ( nextArg >= args.size() ) {
-				if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) {
-					if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) {
-						TypeEnvironment env = results[i].env;
-						AssertionSet need = results[i].need, have = results[i].have;
-						OpenVarSet openVars = results[i].openVars;
-
-						if ( unify( formalType, cnst->get_type(), env, need, have, openVars,
-								indexer ) ) {
-							results.emplace_back(
-								i, new DefaultArgExpr( cnstExpr ), std::move(env), std::move(need), std::move(have),
-								std::move(openVars), nextArg, nTuples );
-						}
-					}
-				}
-
-				continue;
-			}
-
-			// Check each possible next argument
-			for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {
-				const ExplodedActual& expl = args[nextArg][j];
-
-				// fresh copies of parent parameters for this iteration
-				TypeEnvironment env = results[i].env;
-				AssertionSet need = results[i].need, have = results[i].have;
-				OpenVarSet openVars = results[i].openVars;
-
-				env.addActual( expl.env, openVars );
-
-				// skip empty tuple arguments by (near-)cloning parent into next gen
-				if ( expl.exprs.empty() ) {
-					results.emplace_back(
-						results[i], std::move(env), std::move(need), std::move(have), std::move(openVars),
-						nextArg + 1, expl.cost );
-
-					continue;
-				}
-
-				// consider only first exploded actual
-				Expression* expr = expl.exprs.front().get();
-				Type* actualType = expr->result->clone();
-
-				PRINT(
-					std::cerr << "formal type is ";
-					formalType->print( std::cerr );
-					std::cerr << std::endl << "actual type is ";
-					actualType->print( std::cerr );
-					std::cerr << std::endl;
-				)
-
-				// attempt to unify types
-				if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) {
-					// add new result
-					results.emplace_back(
-						i, expr, std::move(env), std::move(need), std::move(have), std::move(openVars), nextArg + 1,
-						nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
-				}
-			}
-		}
-
-		// reset for next parameter
-		genStart = genEnd;
-
-		return genEnd != results.size();
-	}
-
-	template<typename OutputIterator>
-	void AlternativeFinder::Finder::validateFunctionAlternative( const Alternative &func, ArgPack& result,
-			const std::vector<ArgPack>& results, OutputIterator out ) {
-		ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
-		// sum cost and accumulate actuals
-		std::list<Expression*>& args = appExpr->args;
-		Cost cost = func.cost;
-		const ArgPack* pack = &result;
-		while ( pack->expr ) {
-			args.push_front( pack->expr->clone() );
-			cost += pack->cost;
-			pack = &results[pack->parent];
-		}
-		// build and validate new alternative
-		Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost };
-		PRINT(
-			std::cerr << "instantiate function success: " << appExpr << std::endl;
-			std::cerr << "need assertions:" << std::endl;
-			printAssertionSet( result.need, std::cerr, 8 );
-		)
-		inferParameters( newAlt, out );
-	}
-
-	template<typename OutputIterator>
-	void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func,
-			FunctionType *funcType, const ExplodedArgs_old &args, OutputIterator out ) {
-		OpenVarSet funcOpenVars;
-		AssertionSet funcNeed, funcHave;
-		TypeEnvironment funcEnv( func.env );
-		makeUnifiableVars( funcType, funcOpenVars, funcNeed );
-		// add all type variables as open variables now so that those not used in the parameter
-		// list are still considered open.
-		funcEnv.add( funcType->forall );
-
-		if ( targetType && ! targetType->isVoid() && ! funcType->returnVals.empty() ) {
-			// attempt to narrow based on expected target type
-			Type * returnType = funcType->returnVals.front()->get_type();
-			if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars,
-					indexer ) ) {
-				// unification failed, don't pursue this function alternative
-				return;
-			}
-		}
-
-		// iteratively build matches, one parameter at a time
-		std::vector<ArgPack> results;
-		results.push_back( ArgPack{ funcEnv, funcNeed, funcHave, funcOpenVars } );
-		std::size_t genStart = 0;
-
-		for ( DeclarationWithType* formal : funcType->parameters ) {
-			ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal );
-			if ( ! instantiateArgument(
-					obj->type, obj->init, args, results, genStart, indexer ) )
-				return;
-		}
-
-		if ( funcType->get_isVarArgs() ) {
-			// append any unused arguments to vararg pack
-			std::size_t genEnd;
-			do {
-				genEnd = results.size();
-
-				// iterate results
-				for ( std::size_t i = genStart; i < genEnd; ++i ) {
-					auto nextArg = results[i].nextArg;
-
-					// use remainder of exploded tuple if present
-					if ( results[i].hasExpl() ) {
-						const ExplodedActual& expl = results[i].getExpl( args );
-
-						unsigned nextExpl = results[i].nextExpl + 1;
-						if ( nextExpl == expl.exprs.size() ) {
-							nextExpl = 0;
-						}
-
-						results.emplace_back(
-							i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env),
-							copy(results[i].need), copy(results[i].have),
-							copy(results[i].openVars), nextArg, 0, Cost::zero, nextExpl,
-							results[i].explAlt );
-
-						continue;
-					}
-
-					// finish result when out of arguments
-					if ( nextArg >= args.size() ) {
-						validateFunctionAlternative( func, results[i], results, out );
-
-						continue;
-					}
-
-					// add each possible next argument
-					for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {
-						const ExplodedActual& expl = args[nextArg][j];
-
-						// fresh copies of parent parameters for this iteration
-						TypeEnvironment env = results[i].env;
-						OpenVarSet openVars = results[i].openVars;
-
-						env.addActual( expl.env, openVars );
-
-						// skip empty tuple arguments by (near-)cloning parent into next gen
-						if ( expl.exprs.empty() ) {
-							results.emplace_back(
-								results[i], std::move(env), copy(results[i].need),
-								copy(results[i].have), std::move(openVars), nextArg + 1, expl.cost );
-
-							continue;
-						}
-
-						// add new result
-						results.emplace_back(
-							i, expl.exprs.front().get(), std::move(env), copy(results[i].need),
-							copy(results[i].have), std::move(openVars), nextArg + 1, 0,
-							expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
-					}
-				}
-
-				genStart = genEnd;
-			} while ( genEnd != results.size() );
-		} else {
-			// filter out results that don't use all the arguments
-			for ( std::size_t i = genStart; i < results.size(); ++i ) {
-				ArgPack& result = results[i];
-				if ( ! result.hasExpl() && result.nextArg >= args.size() ) {
-					validateFunctionAlternative( func, result, results, out );
-				}
-			}
-		}
-	}
-
-	void AlternativeFinder::Finder::postvisit( UntypedExpr *untypedExpr ) {
-		AlternativeFinder funcFinder( indexer, env );
-		funcFinder.findWithAdjustment( untypedExpr->function );
-		// if there are no function alternatives, then proceeding is a waste of time.
-		// xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary.
-		if ( funcFinder.alternatives.empty() ) return;
-
-		std::vector< AlternativeFinder > argAlternatives;
-		altFinder.findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),
-			back_inserter( argAlternatives ) );
-
-		// take care of possible tuple assignments
-		// if not tuple assignment, assignment is taken care of as a normal function call
-		Tuples::handleTupleAssignment( altFinder, untypedExpr, argAlternatives );
-
-		// find function operators
-		static NameExpr *opExpr = new NameExpr( "?()" );
-		AlternativeFinder funcOpFinder( indexer, env );
-		// it's ok if there aren't any defined function ops
-		funcOpFinder.maybeFind( opExpr );
-		PRINT(
-			std::cerr << "known function ops:" << std::endl;
-			printAlts( funcOpFinder.alternatives, std::cerr, 1 );
-		)
-
-		// pre-explode arguments
-		ExplodedArgs_old argExpansions;
-		argExpansions.reserve( argAlternatives.size() );
-
-		for ( const AlternativeFinder& arg : argAlternatives ) {
-			argExpansions.emplace_back();
-			auto& argE = argExpansions.back();
-			// argE.reserve( arg.alternatives.size() );
-
-			for ( const Alternative& actual : arg ) {
-				argE.emplace_back( actual, indexer );
-			}
-		}
-
-		AltList candidates;
-		SemanticErrorException errors;
-		for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
-			try {
-				PRINT(
-					std::cerr << "working on alternative: " << std::endl;
-					func->print( std::cerr, 8 );
-				)
-				// check if the type is pointer to function
-				if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->result->stripReferences() ) ) {
-					if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->base ) ) {
-						Alternative newFunc( *func );
-						referenceToRvalueConversion( newFunc.expr, newFunc.cost );
-						makeFunctionAlternatives( newFunc, function, argExpansions,
-							std::back_inserter( candidates ) );
-					}
-				} else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->result->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
-					if ( const EqvClass *eqvClass = func->env.lookup( typeInst->name ) ) {
-						if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass->type ) ) {
-							Alternative newFunc( *func );
-							referenceToRvalueConversion( newFunc.expr, newFunc.cost );
-							makeFunctionAlternatives( newFunc, function, argExpansions,
-								std::back_inserter( candidates ) );
-						} // if
-					} // if
-				}
-			} catch ( SemanticErrorException &e ) {
-				errors.append( e );
-			}
-		} // for
-
-		// try each function operator ?() with each function alternative
-		if ( ! funcOpFinder.alternatives.empty() ) {
-			// add exploded function alternatives to front of argument list
-			std::vector<ExplodedActual> funcE;
-			funcE.reserve( funcFinder.alternatives.size() );
-			for ( const Alternative& actual : funcFinder ) {
-				funcE.emplace_back( actual, indexer );
-			}
-			argExpansions.insert( argExpansions.begin(), std::move(funcE) );
-
-			for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin();
-					funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
-				try {
-					// check if type is a pointer to function
-					if ( PointerType* pointer = dynamic_cast<PointerType*>(
-							funcOp->expr->result->stripReferences() ) ) {
-						if ( FunctionType* function =
-								dynamic_cast<FunctionType*>( pointer->base ) ) {
-							Alternative newFunc( *funcOp );
-							referenceToRvalueConversion( newFunc.expr, newFunc.cost );
-							makeFunctionAlternatives( newFunc, function, argExpansions,
-								std::back_inserter( candidates ) );
-						}
-					}
-				} catch ( SemanticErrorException &e ) {
-					errors.append( e );
-				}
-			}
-		}
-
-		// Implement SFINAE; resolution errors are only errors if there aren't any non-erroneous resolutions
-		if ( candidates.empty() && ! errors.isEmpty() ) { throw errors; }
-
-		// compute conversionsion costs
-		for ( Alternative& withFunc : candidates ) {
-			Cost cvtCost = computeApplicationConversionCost( withFunc, indexer );
-
-			PRINT(
-				ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc.expr );
-				PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
-				FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
-				std::cerr << "Case +++++++++++++ " << appExpr->function << std::endl;
-				std::cerr << "formals are:" << std::endl;
-				printAll( function->parameters, std::cerr, 8 );
-				std::cerr << "actuals are:" << std::endl;
-				printAll( appExpr->args, std::cerr, 8 );
-				std::cerr << "bindings are:" << std::endl;
-				withFunc.env.print( std::cerr, 8 );
-				std::cerr << "cost is: " << withFunc.cost << std::endl;
-				std::cerr << "cost of conversion is:" << cvtCost << std::endl;
-			)
-			if ( cvtCost != Cost::infinity ) {
-				withFunc.cvtCost = cvtCost;
-				alternatives.push_back( withFunc );
-			} // if
-		} // for
-
-		candidates = std::move(alternatives);
-
-		// use a new list so that alternatives are not examined by addAnonConversions twice.
-		AltList winners;
-		findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) );
-
-		// function may return struct or union value, in which case we need to add alternatives
-		// for implicit conversions to each of the anonymous members, must happen after findMinCost
-		// since anon conversions are never the cheapest expression
-		for ( const Alternative & alt : winners ) {
-			addAnonConversions( alt );
-		}
-		spliceBegin( alternatives, winners );
-
-		if ( alternatives.empty() && targetType && ! targetType->isVoid() ) {
-			// xxx - this is a temporary hack. If resolution is unsuccessful with a target type, try again without a
-			// target type, since it will sometimes succeed when it wouldn't easily with target type binding. For example,
-			//   forall( otype T ) lvalue T	?[?]( T *, ptrdiff_t );
-			//   const char * x = "hello world";
-			//   unsigned char ch = x[0];
-			// Fails with simple return type binding. First, T is bound to unsigned char, then (x: const char *) is unified
-			// with unsigned char *, which fails because pointer base types must be unified exactly. The new resolver should
-			// fix this issue in a more robust way.
-			targetType = nullptr;
-			postvisit( untypedExpr );
-		}
-	}
-
-	bool isLvalue( Expression *expr ) {
-		// xxx - recurse into tuples?
-		return expr->result && ( expr->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );
-	}
-
-	void AlternativeFinder::Finder::postvisit( AddressExpr *addressExpr ) {
-		AlternativeFinder finder( indexer, env );
-		finder.find( addressExpr->get_arg() );
-		for ( Alternative& alt : finder.alternatives ) {
-			if ( isLvalue( alt.expr ) ) {
-				alternatives.push_back(
-					Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );
-			} // if
-		} // for
-	}
-
-	void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
-		alternatives.push_back( Alternative{ expr->clone(), env } );
-	}
-
-	Expression * restructureCast( Expression * argExpr, Type * toType, bool isGenerated ) {
-		if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) {
-			// Argument expression is a tuple and the target type is not void and not a reference type.
-			// Cast each member of the tuple to its corresponding target type, producing the tuple of those
-			// cast expressions. If there are more components of the tuple than components in the target type,
-			// then excess components do not come out in the result expression (but UniqueExprs ensure that
-			// side effects will still be done).
-			if ( Tuples::maybeImpureIgnoreUnique( argExpr ) ) {
-				// expressions which may contain side effects require a single unique instance of the expression.
-				argExpr = new UniqueExpr( argExpr );
-			}
-			std::list< Expression * > componentExprs;
-			for ( unsigned int i = 0; i < toType->size(); i++ ) {
-				// cast each component
-				TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i );
-				componentExprs.push_back( restructureCast( idx, toType->getComponent( i ), isGenerated ) );
-			}
-			delete argExpr;
-			assert( componentExprs.size() > 0 );
-			// produce the tuple of casts
-			return new TupleExpr( componentExprs );
-		} else {
-			// handle normally
-			CastExpr * ret = new CastExpr( argExpr, toType->clone() );
-			ret->isGenerated = isGenerated;
-			return ret;
-		}
-	}
-
-	void AlternativeFinder::Finder::postvisit( CastExpr *castExpr ) {
-		Type *& toType = castExpr->get_result();
-		assert( toType );
-		toType = resolveTypeof( toType, indexer );
-		assert(!dynamic_cast<TypeofType *>(toType));
-		SymTab::validateType( toType, &indexer );
-		adjustExprType( toType, env, indexer );
-
-		AlternativeFinder finder( indexer, env );
-		finder.targetType = toType;
-		finder.findWithAdjustment( castExpr->arg );
-
-		AltList candidates;
-		for ( Alternative & alt : finder.alternatives ) {
-			AssertionSet needAssertions( alt.need.begin(), alt.need.end() );
-			AssertionSet haveAssertions;
-			OpenVarSet openVars{ alt.openVars };
-
-			alt.env.extractOpenVars( openVars );
-
-			// It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
-			// cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
-			// that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
-			// to.
-			int discardedValues = alt.expr->result->size() - castExpr->result->size();
-			if ( discardedValues < 0 ) continue;
-			// xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
-			// allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
-			// unification run for side-effects
-			unify( castExpr->result, alt.expr->result, alt.env, needAssertions,
-				haveAssertions, openVars, indexer );
-			Cost thisCost =
-				castExpr->isGenerated
-				? conversionCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),	indexer, alt.env )
-				: castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),	indexer, alt.env );
-			PRINT(
-				std::cerr << "working on cast with result: " << castExpr->result << std::endl;
-				std::cerr << "and expr type: " << alt.expr->result << std::endl;
-				std::cerr << "env: " << alt.env << std::endl;
-			)
-			if ( thisCost != Cost::infinity ) {
-				PRINT(
-					std::cerr << "has finite cost." << std::endl;
-				)
-				// count one safe conversion for each value that is thrown away
-				thisCost.incSafe( discardedValues );
-				Alternative newAlt{
-					restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ),
-					alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost };
-				inferParameters( newAlt, back_inserter( candidates ) );
-			} // if
-		} // for
-
-		// findMinCost selects the alternatives with the lowest "cost" members, but has the side effect of copying the
-		// cvtCost member to the cost member (since the old cost is now irrelevant).  Thus, calling findMinCost twice
-		// selects first based on argument cost, then on conversion cost.
-		AltList minArgCost;
-		findMinCost( candidates.begin(), candidates.end(), std::back_inserter( minArgCost ) );
-		findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) );
-	}
-
-	void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
-		assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." );
-		AlternativeFinder finder( indexer, env );
-		// don't prune here, since it's guaranteed all alternatives will have the same type
-		finder.findWithoutPrune( castExpr->get_arg() );
-		for ( Alternative & alt : finder.alternatives ) {
-			alternatives.push_back( Alternative{
-				alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },
-				alt.cost } );
-		}
-	}
-
-	void AlternativeFinder::Finder::postvisit( KeywordCastExpr * castExpr ) {
-		assertf( castExpr->get_result(), "Cast target should have been set in Validate." );
-		auto ref = dynamic_cast<ReferenceType*>(castExpr->get_result());
-		assert(ref);
-		auto inst = dynamic_cast<StructInstType*>(ref->base);
-		assert(inst);
-		auto target = inst->baseStruct;
-
-		AlternativeFinder finder( indexer, env );
-
-		auto pick_alternatives = [target, this](AltList & found, bool expect_ref) {
-			for(auto & alt : found) {
-				Type * expr = alt.expr->get_result();
-				if(expect_ref) {
-					auto res = dynamic_cast<ReferenceType*>(expr);
-					if(!res) { continue; }
-					expr = res->base;
-				}
-
-				if(auto insttype = dynamic_cast<TypeInstType*>(expr)) {
-					auto td = alt.env.lookup(insttype->name);
-					if(!td) { continue; }
-					expr = td->type;
-				}
-
-				if(auto base = dynamic_cast<StructInstType*>(expr)) {
-					if(base->baseStruct == target) {
-						alternatives.push_back(
-							std::move(alt)
-						);
-					}
-				}
-			}
-		};
-
-		try {
-			// Attempt 1 : turn (thread&)X into (thread$&)X.__thrd
-			// Clone is purely for memory management
-			std::unique_ptr<Expression> tech1 { new UntypedMemberExpr(new NameExpr(castExpr->concrete_target.field), castExpr->arg->clone()) };
-
-			// don't prune here, since it's guaranteed all alternatives will have the same type
-			finder.findWithoutPrune( tech1.get() );
-			pick_alternatives(finder.alternatives, false);
-
-			return;
-		} catch(SemanticErrorException & ) {}
-
-		// Fallback : turn (thread&)X into (thread$&)get_thread(X)
-		std::unique_ptr<Expression> fallback { UntypedExpr::createDeref( new UntypedExpr(new NameExpr(castExpr->concrete_target.getter), { castExpr->arg->clone() })) };
-		// don't prune here, since it's guaranteed all alternatives will have the same type
-		finder.findWithoutPrune( fallback.get() );
-
-		pick_alternatives(finder.alternatives, true);
-
-		// Whatever happens here, we have no more fallbacks
-	}
-
-	namespace {
-		/// Gets name from untyped member expression (member must be NameExpr)
-		const std::string& get_member_name( UntypedMemberExpr *memberExpr ) {
-			if ( dynamic_cast< ConstantExpr * >( memberExpr->get_member() ) ) {
-				SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );
-			} // if
-			NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() );
-			assert( nameExpr );
-			return nameExpr->get_name();
-		}
-	}
-
-	void AlternativeFinder::Finder::postvisit( UntypedMemberExpr *memberExpr ) {
-		AlternativeFinder funcFinder( indexer, env );
-		funcFinder.findWithAdjustment( memberExpr->get_aggregate() );
-		for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
-			// it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
-			Cost cost = agg->cost;
-			Expression * aggrExpr = agg->expr->clone();
-			referenceToRvalueConversion( aggrExpr, cost );
-			std::unique_ptr<Expression> guard( aggrExpr );
-
-			// find member of the given type
-			if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
-				addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
-			} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
-				addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
-			} else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
-				addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );
-			} // if
-		} // for
-	}
-
-	void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
-		alternatives.push_back( Alternative{ memberExpr->clone(), env } );
-	}
-
-	void AlternativeFinder::Finder::postvisit( NameExpr *nameExpr ) {
-		std::list< SymTab::Indexer::IdData > declList;
-		indexer.lookupId( nameExpr->name, declList );
-		PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
-		for ( auto & data : declList ) {
-			Cost cost = Cost::zero;
-			Expression * newExpr = data.combine( cost );
-
-			// addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
-			// can't construct in place and use vector::back
-			Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };
-			PRINT(
-				std::cerr << "decl is ";
-				data.id->print( std::cerr );
-				std::cerr << std::endl;
-				std::cerr << "newExpr is ";
-				newExpr->print( std::cerr );
-				std::cerr << std::endl;
-			)
-			renameTypes( newAlt.expr );
-			addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression.
-			alternatives.push_back( std::move(newAlt) );
-		} // for
-	}
-
-	void AlternativeFinder::Finder::postvisit( VariableExpr *variableExpr ) {
-		// not sufficient to clone here, because variable's type may have changed
-		// since the VariableExpr was originally created.
-		alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } );
-	}
-
-	void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
-		alternatives.push_back( Alternative{ constantExpr->clone(), env } );
-	}
-
-	void AlternativeFinder::Finder::postvisit( SizeofExpr *sizeofExpr ) {
-		if ( sizeofExpr->get_isType() ) {
-			Type * newType = sizeofExpr->get_type()->clone();
-			alternatives.push_back( Alternative{
-				new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } );
-		} else {
-			// find all alternatives for the argument to sizeof
-			AlternativeFinder finder( indexer, env );
-			finder.find( sizeofExpr->get_expr() );
-			// find the lowest cost alternative among the alternatives, otherwise ambiguous
-			AltList winners;
-			findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
-			if ( winners.size() != 1 ) {
-				SemanticError( sizeofExpr->get_expr(), "Ambiguous expression in sizeof operand: " );
-			} // if
-			// return the lowest cost alternative for the argument
-			Alternative &choice = winners.front();
-			referenceToRvalueConversion( choice.expr, choice.cost );
-			alternatives.push_back( Alternative{
-				choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } );
-		} // if
-	}
-
-	void AlternativeFinder::Finder::postvisit( AlignofExpr *alignofExpr ) {
-		if ( alignofExpr->get_isType() ) {
-			Type * newType = alignofExpr->get_type()->clone();
-			alternatives.push_back( Alternative{
-				new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } );
-		} else {
-			// find all alternatives for the argument to sizeof
-			AlternativeFinder finder( indexer, env );
-			finder.find( alignofExpr->get_expr() );
-			// find the lowest cost alternative among the alternatives, otherwise ambiguous
-			AltList winners;
-			findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
-			if ( winners.size() != 1 ) {
-				SemanticError( alignofExpr->get_expr(), "Ambiguous expression in alignof operand: " );
-			} // if
-			// return the lowest cost alternative for the argument
-			Alternative &choice = winners.front();
-			referenceToRvalueConversion( choice.expr, choice.cost );
-			alternatives.push_back( Alternative{
-				choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } );
-		} // if
-	}
-
-	template< typename StructOrUnionType >
-	void AlternativeFinder::Finder::addOffsetof( StructOrUnionType *aggInst, const std::string &name ) {
-		std::list< Declaration* > members;
-		aggInst->lookup( name, members );
-		for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
-			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
-				alternatives.push_back( Alternative{
-					new OffsetofExpr{ aggInst->clone(), dwt }, env } );
-				renameTypes( alternatives.back().expr );
-			} else {
-				assert( false );
-			}
-		}
-	}
-
-	void AlternativeFinder::Finder::postvisit( UntypedOffsetofExpr *offsetofExpr ) {
-		AlternativeFinder funcFinder( indexer, env );
-		// xxx - resolveTypeof?
-		if ( StructInstType *structInst = dynamic_cast< StructInstType* >( offsetofExpr->get_type() ) ) {
-			addOffsetof( structInst, offsetofExpr->member );
-		} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( offsetofExpr->get_type() ) ) {
-			addOffsetof( unionInst, offsetofExpr->member );
-		}
-	}
-
-	void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
-		alternatives.push_back( Alternative{ offsetofExpr->clone(), env } );
-	}
-
-	void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
-		alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } );
-	}
-
-	void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) {
-		AlternativeFinder firstFinder( indexer, env );
-		firstFinder.findWithAdjustment( logicalExpr->get_arg1() );
-		if ( firstFinder.alternatives.empty() ) return;
-		AlternativeFinder secondFinder( indexer, env );
-		secondFinder.findWithAdjustment( logicalExpr->get_arg2() );
-		if ( secondFinder.alternatives.empty() ) return;
-		for ( const Alternative & first : firstFinder.alternatives ) {
-			for ( const Alternative & second : secondFinder.alternatives ) {
-				TypeEnvironment compositeEnv{ first.env };
-				compositeEnv.simpleCombine( second.env );
-				OpenVarSet openVars{ first.openVars };
-				mergeOpenVars( openVars, second.openVars );
-				AssertionSet need;
-				cloneAll( first.need, need );
-				cloneAll( second.need, need );
-
-				LogicalExpr *newExpr = new LogicalExpr{
-					first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() };
-				alternatives.push_back( Alternative{
-					newExpr, std::move(compositeEnv), std::move(openVars),
-					AssertionList( need.begin(), need.end() ), first.cost + second.cost } );
-			}
-		}
-	}
-
-	void AlternativeFinder::Finder::postvisit( ConditionalExpr *conditionalExpr ) {
-		// find alternatives for condition
-		AlternativeFinder firstFinder( indexer, env );
-		firstFinder.findWithAdjustment( conditionalExpr->arg1 );
-		if ( firstFinder.alternatives.empty() ) return;
-		// find alternatives for true expression
-		AlternativeFinder secondFinder( indexer, env );
-		secondFinder.findWithAdjustment( conditionalExpr->arg2 );
-		if ( secondFinder.alternatives.empty() ) return;
-		// find alterantives for false expression
-		AlternativeFinder thirdFinder( indexer, env );
-		thirdFinder.findWithAdjustment( conditionalExpr->arg3 );
-		if ( thirdFinder.alternatives.empty() ) return;
-		for ( const Alternative & first : firstFinder.alternatives ) {
-			for ( const Alternative & second : secondFinder.alternatives ) {
-				for ( const Alternative & third : thirdFinder.alternatives ) {
-					TypeEnvironment compositeEnv{ first.env };
-					compositeEnv.simpleCombine( second.env );
-					compositeEnv.simpleCombine( third.env );
-					OpenVarSet openVars{ first.openVars };
-					mergeOpenVars( openVars, second.openVars );
-					mergeOpenVars( openVars, third.openVars );
-					AssertionSet need;
-					cloneAll( first.need, need );
-					cloneAll( second.need, need );
-					cloneAll( third.need, need );
-					AssertionSet have;
-
-					// unify true and false types, then infer parameters to produce new alternatives
-					Type* commonType = nullptr;
-					if ( unify( second.expr->result, third.expr->result, compositeEnv,
-							need, have, openVars, indexer, commonType ) ) {
-						ConditionalExpr *newExpr = new ConditionalExpr{
-							first.expr->clone(), second.expr->clone(), third.expr->clone() };
-						newExpr->result = commonType ? commonType : second.expr->result->clone();
-						// convert both options to the conditional result type
-						Cost cost = first.cost + second.cost + third.cost;
-						cost += computeExpressionConversionCost(
-							newExpr->arg2, newExpr->result, indexer, compositeEnv );
-						cost += computeExpressionConversionCost(
-							newExpr->arg3, newExpr->result, indexer, compositeEnv );
-						// output alternative
-						Alternative newAlt{
-							newExpr, std::move(compositeEnv), std::move(openVars),
-							AssertionList( need.begin(), need.end() ), cost };
-						inferParameters( newAlt, back_inserter( alternatives ) );
-					} // if
-				} // for
-			} // for
-		} // for
-	}
-
-	void AlternativeFinder::Finder::postvisit( CommaExpr *commaExpr ) {
-		TypeEnvironment newEnv( env );
-		Expression *newFirstArg = resolveInVoidContext( commaExpr->get_arg1(), indexer, newEnv );
-		AlternativeFinder secondFinder( indexer, newEnv );
-		secondFinder.findWithAdjustment( commaExpr->get_arg2() );
-		for ( const Alternative & alt : secondFinder.alternatives ) {
-			alternatives.push_back( Alternative{
-				alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } );
-		} // for
-		delete newFirstArg;
-	}
-
-	void AlternativeFinder::Finder::postvisit( RangeExpr * rangeExpr ) {
-		// resolve low and high, accept alternatives whose low and high types unify
-		AlternativeFinder firstFinder( indexer, env );
-		firstFinder.findWithAdjustment( rangeExpr->low );
-		if ( firstFinder.alternatives.empty() ) return;
-		AlternativeFinder secondFinder( indexer, env );
-		secondFinder.findWithAdjustment( rangeExpr->high );
-		if ( secondFinder.alternatives.empty() ) return;
-		for ( const Alternative & first : firstFinder.alternatives ) {
-			for ( const Alternative & second : secondFinder.alternatives ) {
-				TypeEnvironment compositeEnv{ first.env };
-				compositeEnv.simpleCombine( second.env );
-				OpenVarSet openVars{ first.openVars };
-				mergeOpenVars( openVars, second.openVars );
-				AssertionSet need;
-				cloneAll( first.need, need );
-				cloneAll( second.need, need );
-				AssertionSet have;
-
-				Type* commonType = nullptr;
-				if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have,
-						openVars, indexer, commonType ) ) {
-					RangeExpr * newExpr =
-						new RangeExpr{ first.expr->clone(), second.expr->clone() };
-					newExpr->result = commonType ? commonType : first.expr->result->clone();
-					Alternative newAlt{
-						newExpr, std::move(compositeEnv), std::move(openVars),
-						AssertionList( need.begin(), need.end() ), first.cost + second.cost };
-					inferParameters( newAlt, back_inserter( alternatives ) );
-				} // if
-			} // for
-		} // for
-	}
-
-	void AlternativeFinder::Finder::postvisit( UntypedTupleExpr *tupleExpr ) {
-		std::vector< AlternativeFinder > subExprAlternatives;
-		altFinder.findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(),
-			back_inserter( subExprAlternatives ) );
-		std::vector< AltList > possibilities;
-		combos( subExprAlternatives.begin(), subExprAlternatives.end(),
-			back_inserter( possibilities ) );
-		for ( const AltList& alts : possibilities ) {
-			std::list< Expression * > exprs;
-			makeExprList( alts, exprs );
-
-			TypeEnvironment compositeEnv;
-			OpenVarSet openVars;
-			AssertionSet need;
-			for ( const Alternative& alt : alts ) {
-				compositeEnv.simpleCombine( alt.env );
-				mergeOpenVars( openVars, alt.openVars );
-				cloneAll( alt.need, need );
-			}
-
-			alternatives.push_back( Alternative{
-				new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars),
-				AssertionList( need.begin(), need.end() ), sumCost( alts ) } );
-		} // for
-	}
-
-	void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
-		alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
-	}
-
-	void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
-		alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } );
-	}
-
-	void AlternativeFinder::Finder::postvisit( ConstructorExpr * ctorExpr ) {
-		AlternativeFinder finder( indexer, env );
-		// don't prune here, since it's guaranteed all alternatives will have the same type
-		// (giving the alternatives different types is half of the point of ConstructorExpr nodes)
-		finder.findWithoutPrune( ctorExpr->get_callExpr() );
-		for ( Alternative & alt : finder.alternatives ) {
-			alternatives.push_back( Alternative{
-				alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } );
-		}
-	}
-
-	void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
-		alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
-	}
-
-	void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
-		alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } );
-	}
-
-	void AlternativeFinder::Finder::postvisit( UniqueExpr *unqExpr ) {
-		AlternativeFinder finder( indexer, env );
-		finder.findWithAdjustment( unqExpr->get_expr() );
-		for ( Alternative & alt : finder.alternatives ) {
-			// ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked"
-			UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
-			alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } );
-		}
-	}
-
-	void AlternativeFinder::Finder::postvisit( StmtExpr *stmtExpr ) {
-		StmtExpr * newStmtExpr = stmtExpr->clone();
-		ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
-		// xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr...
-		alternatives.push_back( Alternative{ newStmtExpr, env } );
-	}
-
-	void AlternativeFinder::Finder::postvisit( UntypedInitExpr *initExpr ) {
-		// handle each option like a cast
-		AltList candidates;
-		PRINT(
-			std::cerr << "untyped init expr: " << initExpr << std::endl;
-		)
-		// O(N^2) checks of d-types with e-types
-		for ( InitAlternative & initAlt : initExpr->get_initAlts() ) {
-			Type * toType = resolveTypeof( initAlt.type->clone(), indexer );
-			SymTab::validateType( toType, &indexer );
-			adjustExprType( toType, env, indexer );
-			// Ideally the call to findWithAdjustment could be moved out of the loop, but unfortunately it currently has to occur inside or else
-			// polymorphic return types are not properly bound to the initialization type, since return type variables are only open for the duration of resolving
-			// the UntypedExpr. This is only actually an issue in initialization contexts that allow more than one possible initialization type, but it is still suboptimal.
-			AlternativeFinder finder( indexer, env );
-			finder.targetType = toType;
-			finder.findWithAdjustment( initExpr->expr );
-			for ( Alternative & alt : finder.get_alternatives() ) {
-				TypeEnvironment newEnv( alt.env );
-				AssertionSet need;
-				cloneAll( alt.need, need );
-				AssertionSet have;
-				OpenVarSet openVars( alt.openVars );
-				// xxx - find things in env that don't have a "representative type" and claim
-				// those are open vars?
-				PRINT(
-					std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
-				)
-				// It's possible that a cast can throw away some values in a multiply-valued
-				// expression. (An example is a cast-to-void, which casts from one value to
-				// zero.)  Figure out the prefix of the subexpression results that are cast
-				// directly.  The candidate is invalid if it has fewer results than there are
-				// types to cast to.
-				int discardedValues = alt.expr->result->size() - toType->size();
-				if ( discardedValues < 0 ) continue;
-				// xxx - may need to go into tuple types and extract relevant types and use
-				// unifyList. Note that currently, this does not allow casting a tuple to an
-				// atomic type (e.g. (int)([1, 2, 3]))
-
-				// unification run for side-effects
-				bool canUnify = unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
-				(void) canUnify;
-				// xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
-
-				Cost thisCost = computeConversionCost( alt.expr->result, toType, alt.expr->get_lvalue(),
-					indexer, newEnv );
-
-				PRINT(
-					Cost legacyCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(),
-						indexer, newEnv );
-					std::cerr << "Considering initialization:";
-					std::cerr << std::endl << "  FROM: "; alt.expr->result->print(std::cerr);
-					std::cerr << std::endl << "  TO: ";   toType          ->print(std::cerr);
-					std::cerr << std::endl << "  Unification " << (canUnify ? "succeeded" : "failed");
-					std::cerr << std::endl << "  Legacy cost " << legacyCost;
-					std::cerr << std::endl << "  New cost " << thisCost;
-					std::cerr << std::endl;
-				)
-
-				if ( thisCost != Cost::infinity ) {
-					// count one safe conversion for each value that is thrown away
-					thisCost.incSafe( discardedValues );
-					Alternative newAlt{
-						new InitExpr{
-							restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() },
-						std::move(newEnv), std::move(openVars),
-						AssertionList( need.begin(), need.end() ), alt.cost, thisCost };
-					inferParameters( newAlt, back_inserter( candidates ) );
-				}
-			}
-		}
-
-		// findMinCost selects the alternatives with the lowest "cost" members, but has the side effect of copying the
-		// cvtCost member to the cost member (since the old cost is now irrelevant).  Thus, calling findMinCost twice
-		// selects first based on argument cost, then on conversion cost.
-		AltList minArgCost;
-		findMinCost( candidates.begin(), candidates.end(), std::back_inserter( minArgCost ) );
-		findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) );
-	}
-
-	void AlternativeFinder::Finder::postvisit( InitExpr * ) {
-		assertf( false, "AlternativeFinder should never see a resolved InitExpr." );
-	}
-
-	void AlternativeFinder::Finder::postvisit( DeletedExpr * ) {
-		assertf( false, "AlternativeFinder should never see a DeletedExpr." );
-	}
-
-	void AlternativeFinder::Finder::postvisit( GenericExpr * ) {
-		assertf( false, "_Generic is not yet supported." );
-	}
-} // namespace ResolvExpr
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,150 +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.
-//
-// AlternativeFinder.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sat May 16 23:56:12 2015
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Fri Oct -5 10:01:00 2018
-// Update Count     : 5
-//
-
-#pragma once
-
-#include <algorithm>                     // for copy
-#include <list>                          // for list
-#include <string>                        // for string
-
-#include "Alternative.h"                 // for AltList, Alternative
-#include "ExplodedActual.h"              // for ExplodedActual
-#include "ResolvExpr/Cost.h"             // for Cost, Cost::infinity
-#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
-#include "ResolvMode.h"                  // for ResolvMode
-#include "SynTree/Visitor.h"             // for Visitor
-#include "SynTree/SynTree.h"             // for Visitor Nodes
-
-namespace SymTab {
-class Indexer;
-}  // namespace SymTab
-
-namespace ResolvExpr {
-	struct ArgPack;
-
-	Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue,
-		const SymTab::Indexer & indexer, const TypeEnvironment & env );
-
-	void referenceToRvalueConversion( Expression *& expr, Cost & cost );
-
-	/// First index is which argument, second index is which alternative for that argument,
-	/// third index is which exploded element of that alternative
-	using ExplodedArgs_old = std::vector< std::vector< ExplodedActual > >;
-
-	class AlternativeFinder {
-	  public:
-		AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env );
-
-		AlternativeFinder( const AlternativeFinder& o )
-			: indexer(o.indexer), alternatives(o.alternatives), env(o.env),
-			  targetType(o.targetType) {}
-
-		AlternativeFinder( AlternativeFinder&& o )
-			: indexer(o.indexer), alternatives(std::move(o.alternatives)), env(o.env),
-			  targetType(o.targetType) {}
-
-		AlternativeFinder& operator= ( const AlternativeFinder& o ) {
-			if (&o == this) return *this;
-
-			// horrific nasty hack to rebind references...
-			alternatives.~AltList();
-			new(this) AlternativeFinder(o);
-			return *this;
-		}
-
-		AlternativeFinder& operator= ( AlternativeFinder&& o ) {
-			if (&o == this) return *this;
-
-			// horrific nasty hack to rebind references...
-			alternatives.~AltList();
-			new(this) AlternativeFinder(std::move(o));
-			return *this;
-		}
-
-		void find( Expression *expr, ResolvMode mode = ResolvMode{} );
-		/// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types
-		void findWithAdjustment( Expression *expr );
-		/// Calls find with the adjust flag set and prune flag unset; pruning ensures there is at most one alternative per result type
-		void findWithoutPrune( Expression *expr );
-		/// Calls find with the adjust and prune flags set, failFast flags unset; fail fast ensures that there is at least one resulting alternative
-		void maybeFind( Expression *expr );
-		AltList &get_alternatives() { return alternatives; }
-
-		// make this look like an STL container so that we can apply generic algorithms
-		typedef Alternative value_type;
-		typedef AltList::iterator iterator;
-		typedef AltList::const_iterator const_iterator;
-		AltList::iterator begin() { return alternatives.begin(); }
-		AltList::iterator end() { return alternatives.end(); }
-		AltList::const_iterator begin() const { return alternatives.begin(); }
-		AltList::const_iterator end() const { return alternatives.end(); }
-
-		const SymTab::Indexer &get_indexer() const { return indexer; }
-		const TypeEnvironment &get_environ() const { return env; }
-
-		/// Runs a new alternative finder on each element in [begin, end)
-		/// and writes each alternative finder to out.
-		template< typename InputIterator, typename OutputIterator >
-		void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
-	  private:
-		struct Finder;
-		const SymTab::Indexer &indexer;
-		AltList alternatives;
-		const TypeEnvironment &env;
-		Type * targetType = nullptr;
-	}; // AlternativeFinder
-
-	Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env );
-
-	template< typename InputIterator, typename OutputIterator >
-	void findMinCost( InputIterator begin, InputIterator end, OutputIterator out ) {
-		AltList alternatives;
-
-		// select the alternatives that have the minimum parameter cost
-		Cost minCost = Cost::infinity;
-		for ( InputIterator i = begin; i != end; ++i ) {
-			if ( i->cost < minCost ) {
-				minCost = i->cost;
-				i->cost = i->cvtCost;
-				alternatives.clear();
-				alternatives.push_back( *i );
-			} else if ( i->cost == minCost ) {
-				i->cost = i->cvtCost;
-				alternatives.push_back( *i );
-			}
-		}
-		std::copy( alternatives.begin(), alternatives.end(), out );
-	}
-
-	Cost sumCost( const AltList &in );
-	void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt = 0 );
-
-	/// Adds type variables to the open variable set and marks their assertions
-	void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions );
-
-	template< typename InputIterator >
-	void simpleCombineEnvironments( InputIterator begin, InputIterator end, TypeEnvironment &result ) {
-		while ( begin != end ) {
-			result.simpleCombine( (*begin++).env );
-		}
-	}
-
-} // namespace ResolvExpr
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ResolvExpr/AlternativePrinter.cc
===================================================================
--- src/ResolvExpr/AlternativePrinter.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,49 +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.
-//
-// AlternativePrinter.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 06:53:19 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sun May 17 06:55:05 2015
-// Update Count     : 2
-//
-
-#include "AlternativePrinter.h"
-
-#include <list>                          // for _List_const_iterator, list<>...
-
-#include "Alternative.h"                 // for AltList, Alternative
-#include "AlternativeFinder.h"           // for AlternativeFinder
-#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
-#include "SynTree/Expression.h"          // for Expression
-#include "SynTree/Statement.h"           // for ExprStmt
-#include "SynTree/Type.h"                // for Type
-
-namespace ResolvExpr {
-	AlternativePrinter::AlternativePrinter( std::ostream &os ) : os( os ) {}
-
-	void AlternativePrinter::postvisit( ExprStmt *exprStmt ) {
-		TypeEnvironment env;
-		AlternativeFinder finder( indexer, env );
-		finder.findWithAdjustment( exprStmt->get_expr() );
-		int count = 1;
-		os << "There are " << finder.get_alternatives().size() << " alternatives" << std::endl;
-		for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
-			os << "Alternative " << count++ << " ==============" << std::endl;
-			i->expr->get_result()->print( os );
-			//    i->print( os );
-			os << std::endl;
-		} // for
-	} // AlternativePrinter::visit
-} // namespace ResolvExpr
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ResolvExpr/AlternativePrinter.h
===================================================================
--- src/ResolvExpr/AlternativePrinter.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,39 +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.
-//
-// AlternativePrinter.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 06:55:43 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:37:09 2017
-// Update Count     : 4
-//
-
-#pragma once
-
-#include <iostream>          // for ostream
-
-#include "Common/PassVisitor.h"
-
-class ExprStmt;
-
-namespace ResolvExpr {
-	class AlternativePrinter final : public WithIndexer {
-	  public:
-		AlternativePrinter( std::ostream &os );
-
-		void postvisit( ExprStmt *exprStmt );
-	  private:
-		std::ostream &os;
-	};
-} // namespace ResolvExpr
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -61,5 +61,5 @@
 namespace {
 	/// First index is which argument, second is which alternative, third is which exploded element
-	using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >;
+	using ExplodedArgs = std::deque< std::vector< ExplodedArg > >;
 
 	/// Returns a list of alternatives with the minimum cost in the given list
@@ -255,5 +255,5 @@
 
 		/// Gets the list of exploded candidates for this pack
-		const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const {
+		const ExplodedArg & getExpl( const ExplodedArgs & args ) const {
 			return args[ nextArg-1 ][ explAlt ];
 		}
@@ -281,5 +281,5 @@
 	bool instantiateArgument(
 		const CodeLocation & location,
-		const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,
+		const ast::Type * paramType, const ast::Init * init, const ExplodedArgs & args,
 		std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,
 		unsigned nTuples = 0
@@ -618,5 +618,5 @@
 			const CodeLocation & location,
 			const CandidateRef & func, const ast::FunctionType * funcType,
-			const ExplodedArgs_new & args, CandidateList & out );
+			const ExplodedArgs & args, CandidateList & out );
 
 		/// Adds implicit struct-conversions to the alternative list
@@ -737,5 +737,5 @@
 		const CodeLocation & location,
 		const CandidateRef & func, const ast::FunctionType * funcType,
-		const ExplodedArgs_new & args, CandidateList & out
+		const ExplodedArgs & args, CandidateList & out
 	) {
 		ast::OpenVarSet funcOpen;
@@ -997,5 +997,5 @@
 
 		// pre-explode arguments
-		ExplodedArgs_new argExpansions;
+		ExplodedArgs argExpansions;
 		for ( const CandidateFinder & args : argCandidates ) {
 			argExpansions.emplace_back();
Index: src/ResolvExpr/CastCost.cc
===================================================================
--- src/ResolvExpr/CastCost.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/CastCost.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -26,10 +26,5 @@
 #include "ResolvExpr/ConversionCost.h"   // for conversionCost
 #include "ResolvExpr/PtrsCastable.hpp"   // for ptrsCastable
-#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment, EqvClass
-#include "ResolvExpr/typeops.h"          // for ptrsCastable
 #include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
-#include "SymTab/Indexer.h"              // for Indexer
-#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
-#include "SynTree/Type.h"                // for PointerType, Type, TypeInstType
 
 #if 0
@@ -40,114 +35,14 @@
 
 namespace ResolvExpr {
-	struct CastCost_old : public ConversionCost {
-	  public:
-		CastCost_old( const Type * dest, bool srcIsLvalue,
-			const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
 
+namespace {
+	struct CastCost : public ConversionCost {
 		using ConversionCost::previsit;
 		using ConversionCost::postvisit;
-		void postvisit( const BasicType * basicType );
-		void postvisit( const PointerType * pointerType );
-	};
 
-	Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue,
-			const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
-		if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
-			if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
-				if ( eqvClass->type ) {
-					return castCost( src, eqvClass->type, srcIsLvalue, indexer, env );
-				} else {
-					return Cost::infinity;
-				}
-			} else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
-				// all typedefs should be gone by this point
-				const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( namedType );
-				if ( type->base ) {
-					return castCost( src, type->base, srcIsLvalue, indexer, env ) + Cost::safe;
-				} // if
-			} // if
-		} // if
-
-		PRINT(
-			std::cerr << "castCost ::: src is ";
-			src->print( std::cerr );
-			std::cerr << std::endl << "dest is ";
-			dest->print( std::cerr );
-			std::cerr << std::endl << "env is" << std::endl;
-			env.print( std::cerr, 8 );
-		)
-
-		if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
-			PRINT( std::cerr << "compatible!" << std::endl; )
-			return Cost::zero;
-		} else if ( dynamic_cast< const VoidType * >( dest ) ) {
-			return Cost::safe;
-		} else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
-			PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
-			return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * t1, const Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
-				return ptrsCastable( t1, t2, env, indexer );
-			});
-		} else {
-			PassVisitor<CastCost_old> converter(
-				dest, srcIsLvalue, indexer, env,
-				(Cost (*)( const Type *, const Type *, bool, const SymTab::Indexer &, const TypeEnvironment & ))
-					castCost );
-			src->accept( converter );
-			if ( converter.pass.get_cost() == Cost::infinity ) {
-				return Cost::infinity;
-			} else {
-				// xxx - why are we adding cost 0 here?
-				return converter.pass.get_cost() + Cost::zero;
-			} // if
-		} // if
-	}
-
-	CastCost_old::CastCost_old( const Type * dest, bool srcIsLvalue,
-			const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
-		: ConversionCost( dest, srcIsLvalue, indexer, env, costFunc ) {
-	}
-
-	void CastCost_old::postvisit( const BasicType * basicType ) {
-		const PointerType * destAsPointer = dynamic_cast< const PointerType * >( dest );
-		if ( destAsPointer && basicType->isInteger() ) {
-			// necessary for, e.g. unsigned long => void *
-			cost = Cost::unsafe;
-		} else {
-			cost = conversionCost( basicType, dest, srcIsLvalue, indexer, env );
-		} // if
-	}
-
-	void CastCost_old::postvisit( const PointerType * pointerType ) {
-		if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
-			if ( pointerType->tq <= destAsPtr->tq && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
-				cost = Cost::safe;
-			} else {
-				TypeEnvironment newEnv( env );
-				newEnv.add( pointerType->forall );
-				newEnv.add( pointerType->base->forall );
-				int castResult = ptrsCastable( pointerType->base, destAsPtr->base, newEnv, indexer );
-				if ( castResult > 0 ) {
-					cost = Cost::safe;
-				} else if ( castResult < 0 ) {
-					cost = Cost::infinity;
-				} // if
-			} // if
-		} else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
-			if ( destAsBasic->isInteger() ) {
-				// necessary for, e.g. void * => unsigned long
-				cost = Cost::unsafe;
-			} // if
-		}
-	}
-
-namespace {
-	struct CastCost_new : public ConversionCost_new {
-		using ConversionCost_new::previsit;
-		using ConversionCost_new::postvisit;
-
-		CastCost_new(
+		CastCost(
 			const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
 			const ast::TypeEnvironment & env, CostCalculation costFunc )
-		: ConversionCost_new( dst, srcIsLvalue, symtab, env, costFunc ) {}
+		: ConversionCost( dst, srcIsLvalue, symtab, env, costFunc ) {}
 
 		void postvisit( const ast::BasicType * basicType ) {
@@ -189,16 +84,5 @@
 	};
 
-	#warning For overload resolution between the two versions.
-	int localPtrsCastable(const ast::Type * t1, const ast::Type * t2,
-			const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) {
-		return ptrsCastable( t1, t2, symtab, env );
-	}
-	Cost localCastCost(
-		const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
-		const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
-	) { return castCost( src, dst, srcIsLvalue, symtab, env ); }
 } // anonymous namespace
-
-
 
 Cost castCost(
@@ -242,11 +126,9 @@
 	} else if ( auto refType = dynamic_cast< const ast::ReferenceType * >( dst ) ) {
 		PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
-		#warning cast on ptrsCastable artifact of having two functions, remove when port done
 		return convertToReferenceCost(
-			src, refType, srcIsLvalue, symtab, env, localPtrsCastable );
+			src, refType, srcIsLvalue, symtab, env, ptrsCastable );
 	} else {
-		#warning cast on castCost artifact of having two functions, remove when port done
-		ast::Pass< CastCost_new > converter(
-			dst, srcIsLvalue, symtab, env, localCastCost );
+		ast::Pass< CastCost > converter(
+			dst, srcIsLvalue, symtab, env, castCost );
 		src->accept( converter );
 		return converter.core.cost;
Index: src/ResolvExpr/CastCost.hpp
===================================================================
--- src/ResolvExpr/CastCost.hpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/CastCost.hpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -18,8 +18,4 @@
 #include "ResolvExpr/Cost.h"     // for Cost
 
-class Type;
-namespace SymTab {
-	class Indexer;
-}
 namespace ast {
 	class SymbolTable;
@@ -30,9 +26,4 @@
 namespace ResolvExpr {
 
-class TypeEnvironment;
-
-Cost castCost(
-	const Type * src, const Type * dest, bool srcIsLvalue,
-	const SymTab::Indexer & indexer, const TypeEnvironment & env );
 Cost castCost(
 	const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/CommonType.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -23,10 +23,4 @@
 #include "AST/Pass.hpp"
 #include "AST/Type.hpp"
-#include "Common/PassVisitor.h"
-#include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
-#include "SymTab/Indexer.h"              // for Indexer
-#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl (ptr...
-#include "SynTree/Type.h"                // for BasicType, BasicType::Kind::...
-#include "SynTree/Visitor.h"             // for Visitor
 #include "Unify.h"                       // for unifyExact, WidenMode
 #include "typeops.h"                     // for isFtype
@@ -41,144 +35,4 @@
 
 namespace ResolvExpr {
-	struct CommonType_old : public WithShortCircuiting {
-		CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
-		Type * get_result() const { return result; }
-
-		void previsit( BaseSyntaxNode * ) { visit_children = false; }
-
-		void postvisit( VoidType * voidType );
-		void postvisit( BasicType * basicType );
-		void postvisit( PointerType * pointerType );
-		void postvisit( ArrayType * arrayType );
-		void postvisit( ReferenceType * refType );
-		void postvisit( FunctionType * functionType );
-		void postvisit( StructInstType * aggregateUseType );
-		void postvisit( UnionInstType * aggregateUseType );
-		void postvisit( EnumInstType * aggregateUseType );
-		void postvisit( TraitInstType * aggregateUseType );
-		void postvisit( TypeInstType * aggregateUseType );
-		void postvisit( TupleType * tupleType );
-		void postvisit( VarArgsType * varArgsType );
-		void postvisit( ZeroType * zeroType );
-		void postvisit( OneType * oneType );
-
-	  private:
-		template< typename Pointer > void getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer );
-		template< typename RefType > void handleRefType( RefType * inst, Type * other );
-
-		Type * result;
-		Type * type2;				// inherited
-		bool widenFirst, widenSecond;
-		const SymTab::Indexer &indexer;
-		TypeEnvironment &env;
-		const OpenVarSet &openVars;
-	};
-
-	Type * handleReference( Type * t1, Type * t2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {
-		Type * common = nullptr;
-		AssertionSet have, need;
-		OpenVarSet newOpen( openVars );
-		// need unify to bind type variables
-		if ( unify( t1, t2, env, have, need, newOpen, indexer, common ) ) {
-			PRINT(
-				std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
-			)
-			if ( (widenFirst || t2->tq <= t1->tq) && (widenSecond || t1->tq <= t2->tq) ) {
-				PRINT(
-					std::cerr << "widen okay" << std::endl;
-				)
-				common->tq |= t1->tq;
-				common->tq |= t2->tq;
-				return common;
-			}
-		}
-		PRINT(
-			std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
-		)
-		return nullptr;
-	}
-
-	Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
-		PassVisitor<CommonType_old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
-
-		int depth1 = type1->referenceDepth();
-		int depth2 = type2->referenceDepth();
-		if ( depth1 > 0 || depth2 > 0 ) {
-			int diff = depth1-depth2;
-			// TODO: should it be possible for commonType to generate complicated conversions? I would argue no, only conversions that involve types of the same reference level or a difference of 1 should be allowed.
-			// if ( diff > 1 || diff < -1 ) return nullptr;
-
-			// special case where one type has a reference depth of 1 larger than the other
-			if ( diff > 0 || diff < 0 ) {
-				PRINT(
-					std::cerr << "reference depth diff: " << diff << std::endl;
-				)
-				Type * result = nullptr;
-				ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 );
-				ReferenceType * ref2 = dynamic_cast< ReferenceType * >( type2 );
-				if ( diff > 0 ) {
-					// deeper on the left
-					assert( ref1 );
-					result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars );
-				} else {
-					// deeper on the right
-					assert( ref2 );
-					result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars );
-				}
-				if ( result && ref1 ) {
-					// formal is reference, so result should be reference
-					PRINT(
-						std::cerr << "formal is reference; result should be reference" << std::endl;
-					)
-					result = new ReferenceType( ref1->tq, result );
-				}
-				PRINT(
-					std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl;
-				)
-				return result;
-			}
-			// otherwise, both are reference types of the same depth and this is handled by the CommonType visitor.
-		}
-
-		type1->accept( visitor );
-		Type * result = visitor.pass.get_result();
-		if ( ! result ) {
-			// this appears to be handling for opaque type declarations
-			if ( widenSecond ) {
-				if ( const TypeInstType * inst = dynamic_cast< const TypeInstType * >( type2 ) ) {
-					if ( const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() ) ) {
-						const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt );
-						if ( type->get_base() ) {
-							Type::Qualifiers tq1 = type1->tq, tq2 = type2->tq;
-							AssertionSet have, need;
-							OpenVarSet newOpen( openVars );
-							type1->tq = Type::Qualifiers();
-							type->get_base()->tq = tq1;
-							if ( unifyExact( type1, type->get_base(), env, have, need, newOpen, indexer ) ) {
-								result = type1->clone();
-								result->tq = tq1 | tq2;
-							} // if
-							type1->tq = tq1;
-							type->get_base()->tq = Type::Qualifiers();
-						} // if
-					} // if
-				} // if
-			} // if
-		} // if
-#ifdef DEBUG
-		std::cerr << "============= commonType" << std::endl << "type1 is ";
-		type1->print( std::cerr );
-		std::cerr << " type2 is ";
-		type2->print( std::cerr );
-		if ( result ) {
-			std::cerr << " common type is ";
-			result->print( std::cerr );
-		} else {
-			std::cerr << " no common type";
-		} // if
-		std::cerr << std::endl;
-#endif
-		return result;
-	}
 
 	// GENERATED START, DO NOT EDIT
@@ -489,189 +343,5 @@
 	);
 
-	CommonType_old::CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
-		: result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) {
-	}
-
-	void CommonType_old::postvisit( VoidType * ) {}
-
-	void CommonType_old::postvisit( BasicType * basicType ) {
-		if ( BasicType * otherBasic = dynamic_cast< BasicType * >( type2 ) ) {
-			BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ (ast::BasicType::Kind)(int)otherBasic->get_kind() ];
-			if ( ( ( newType == basicType->get_kind() && basicType->tq >= otherBasic->tq ) || widenFirst ) && ( ( newType == otherBasic->get_kind() && basicType->tq <= otherBasic->tq ) || widenSecond ) ) {
-				result = new BasicType( basicType->tq | otherBasic->tq, newType );
-			} // if
-		} else if (  dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
-			// use signed int in lieu of the enum/zero/one type
-			BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ ast::BasicType::SignedInt ];
-			if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) {
-				result = new BasicType( basicType->tq | type2->tq, newType );
-			} // if
-		} else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * > ( type2 ) ) {
-			const EnumDecl* enumDecl = enumInst->baseEnum;
-			if ( const Type* baseType = enumDecl->base ) {
-				result = baseType->clone();
-			} else {
-				BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ ast::BasicType::SignedInt ];
-				if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) {
-					result = new BasicType( basicType->tq | type2->tq, newType );
-				} // if
-			}
-		}
-	}
-
-	template< typename Pointer >
-	void CommonType_old::getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer ) {
-		if ( TypeInstType * var = dynamic_cast< TypeInstType * >( otherPointer->get_base() ) ) {
-			OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
-			if ( entry != openVars.end() ) {
-				AssertionSet need, have;
-				WidenMode widen( widenFirst, widenSecond );
-				if ( entry != openVars.end() && ! env.bindVar(var, voidPointer->get_base(), entry->second, need, have, openVars, widen, indexer ) ) return;
-			}
-		}
-		result = voidPointer->clone();
-		result->tq |= otherPointer->tq;
-	}
-
-	void CommonType_old::postvisit( PointerType * pointerType ) {
-		if ( PointerType * otherPointer = dynamic_cast< PointerType * >( type2 ) ) {
-			// std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
-			if ( widenFirst && dynamic_cast< VoidType * >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) {
-				getCommonWithVoidPointer( otherPointer, pointerType );
-			} else if ( widenSecond && dynamic_cast< VoidType * >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base()) ) {
-				getCommonWithVoidPointer( pointerType, otherPointer );
-			} else if ( ( pointerType->get_base()->tq >= otherPointer->get_base()->tq || widenFirst )
-					   && ( pointerType->get_base()->tq <= otherPointer->get_base()->tq || widenSecond ) ) {
-				// std::cerr << "middle case" << std::endl;
-				Type::Qualifiers tq1 = pointerType->get_base()->tq, tq2 = otherPointer->get_base()->tq;
-				pointerType->get_base()->tq = Type::Qualifiers();
-				otherPointer->get_base()->tq = Type::Qualifiers();
-				AssertionSet have, need;
-				OpenVarSet newOpen( openVars );
-				if ( unifyExact( pointerType->get_base(), otherPointer->get_base(), env, have, need, newOpen, indexer ) ) {
-					// std::cerr << "unifyExact success" << std::endl;
-					if ( tq1 < tq2 ) {
-						result = pointerType->clone();
-					} else {
-						result = otherPointer->clone();
-					} // if
-					strict_dynamic_cast<PointerType *>(result)->base->tq = tq1 | tq2;
-				} else {
-					/// std::cerr << "place for ptr-to-type" << std::endl;
-				} // if
-				pointerType->get_base()->tq = tq1;
-				otherPointer->get_base()->tq = tq2;
-			} // if
-		} else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
-			result = pointerType->clone();
-			result->tq |= type2->tq;
-		} // if
-	}
-
-	void CommonType_old::postvisit( ArrayType * ) {}
-
-	void CommonType_old::postvisit( ReferenceType * refType ) {
-		if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( type2 ) ) {
-			// std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
-			// std::cerr << ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst ) << (refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond) << std::endl;
-			if ( widenFirst && dynamic_cast< VoidType * >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {
-				getCommonWithVoidPointer( otherRef, refType );
-			} else if ( widenSecond && dynamic_cast< VoidType * >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
-				getCommonWithVoidPointer( refType, otherRef );
-			} else if ( ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst )
-					   && ( refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond ) ) {
-				// std::cerr << "middle case" << std::endl;
-				Type::Qualifiers tq1 = refType->get_base()->tq, tq2 = otherRef->get_base()->tq;
-				refType->get_base()->tq = Type::Qualifiers();
-				otherRef->get_base()->tq = Type::Qualifiers();
-				AssertionSet have, need;
-				OpenVarSet newOpen( openVars );
-				if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) {
-					if ( tq1 < tq2 ) {
-						result = refType->clone();
-					} else {
-						result = otherRef->clone();
-					} // if
-					strict_dynamic_cast<ReferenceType *>(result)->base->tq = tq1 | tq2;
-				} else {
-					/// std::cerr << "place for ptr-to-type" << std::endl;
-				} // if
-				refType->get_base()->tq = tq1;
-				otherRef->get_base()->tq = tq2;
-			} // if
-		} else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
-			result = refType->clone();
-			result->tq |= type2->tq;
-		} // if
-	}
-
-	void CommonType_old::postvisit( FunctionType * ) {}
-	void CommonType_old::postvisit( StructInstType * ) {}
-	void CommonType_old::postvisit( UnionInstType * ) {}
-
-	void CommonType_old::postvisit( EnumInstType * enumInstType ) {
-		if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
-			// reuse BasicType, EnumInstType code by swapping type2 with enumInstType
-			result = commonType( type2, enumInstType, widenSecond, widenFirst, indexer, env, openVars );
-		} // if
-	}
-
-	void CommonType_old::postvisit( TraitInstType * ) {
-	}
-
-	void CommonType_old::postvisit( TypeInstType * inst ) {
-		if ( widenFirst ) {
-			const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() );
-			if ( nt ) {
-				const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt );
-				if ( type->get_base() ) {
-					Type::Qualifiers tq1 = inst->tq, tq2 = type2->tq;
-					AssertionSet have, need;
-					OpenVarSet newOpen( openVars );
-					type2->tq = Type::Qualifiers();
-					type->get_base()->tq = tq1;
-					if ( unifyExact( type->get_base(), type2, env, have, need, newOpen, indexer ) ) {
-						result = type2->clone();
-						result->tq = tq1 | tq2;
-					} // if
-					type2->tq = tq2;
-					type->get_base()->tq = Type::Qualifiers();
-				} // if
-			} // if
-		} // if
-	}
-
-	void CommonType_old::postvisit( TupleType * ) {}
-	void CommonType_old::postvisit( VarArgsType * ) {}
-
-	void CommonType_old::postvisit( ZeroType * zeroType ) {
-		if ( widenFirst ) {
-			if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< PointerType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
-				if ( widenSecond || zeroType->tq <= type2->tq ) {
-					result = type2->clone();
-					result->tq |= zeroType->tq;
-				}
-			} else if ( widenSecond && dynamic_cast< OneType * >( type2 ) ) {
-				result = new BasicType( zeroType->tq, BasicType::SignedInt );
-				result->tq |= type2->tq;
-			}
-		}
-	}
-
-	void CommonType_old::postvisit( OneType * oneType ) {
-		if ( widenFirst ) {
-			if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
-				if ( widenSecond || oneType->tq <= type2->tq ) {
-					result = type2->clone();
-					result->tq |= oneType->tq;
-				}
-			} else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
-				result = new BasicType( oneType->tq, BasicType::SignedInt );
-				result->tq |= type2->tq;
-			}
-		}
-	}
-
-	class CommonType_new final : public ast::WithShortCircuiting {
+	class CommonType final : public ast::WithShortCircuiting {
 		const ast::Type * type2;
 		WidenMode widen;
@@ -684,5 +354,5 @@
 		ast::ptr< ast::Type > result;
 
-		CommonType_new(
+		CommonType(
 			const ast::Type * t2, WidenMode w,
 			ast::TypeEnvironment & env, const ast::OpenVarSet & o,
@@ -718,5 +388,4 @@
 					result = enumDecl->base.get();
 				} else {
-					#warning remove casts when `commonTypes` moved to new AST
 					ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ];
 					if (
@@ -1069,5 +738,5 @@
 	};
 
-	// size_t CommonType_new::traceId = Stats::Heap::new_stacktrace_id("CommonType_new");
+	// size_t CommonType::traceId = Stats::Heap::new_stacktrace_id("CommonType");
 	namespace {
 		ast::ptr< ast::Type > handleReference(
@@ -1141,5 +810,5 @@
 		}
 		// otherwise both are reference types of the same depth and this is handled by the visitor
-		ast::Pass<CommonType_new> visitor{ type2, widen, env, open, need, have };
+		ast::Pass<CommonType> visitor{ type2, widen, env, open, need, have };
 		type1->accept( visitor );
 		// ast::ptr< ast::Type > result = visitor.core.result;
Index: src/ResolvExpr/CommonType.hpp
===================================================================
--- src/ResolvExpr/CommonType.hpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/CommonType.hpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -18,18 +18,8 @@
 #include "AST/Fwd.hpp"
 #include "AST/TypeEnvironment.hpp"  // for AssertionSet, OpenVarSet
-#include "TypeEnvironment.h"        // for AssertionSet, OpenVarSet
 #include "WidenMode.h"              // for WidenMode
-
-class Type;
-namespace SymTab {
-	class Indexer;
-}
 
 namespace ResolvExpr {
 
-Type * commonType(
-	Type * type1, Type * type2, bool widenFirst, bool widenSecond,
-	const SymTab::Indexer & indexer, TypeEnvironment & env,
-	const OpenVarSet & openVars );
 ast::ptr< ast::Type > commonType(
 	const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/ConversionCost.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -21,24 +21,8 @@
 
 #include "ResolvExpr/Cost.h"             // for Cost
-#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
 #include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
 #include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
-#include "SymTab/Indexer.h"              // for Indexer
-#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
-#include "SynTree/Type.h"                // for Type, BasicType, TypeInstType
-
 
 namespace ResolvExpr {
-#if 0
-	const Cost Cost::zero =      Cost{  0,  0,  0,  0,  0,  0,  0 };
-	const Cost Cost::infinity =  Cost{ -1, -1, -1, -1, -1,  1, -1 };
-	const Cost Cost::unsafe =    Cost{  1,  0,  0,  0,  0,  0,  0 };
-	const Cost Cost::poly =      Cost{  0,  1,  0,  0,  0,  0,  0 };
-	const Cost Cost::safe =      Cost{  0,  0,  1,  0,  0,  0,  0 };
-	const Cost Cost::sign =      Cost{  0,  0,  0,  1,  0,  0,  0 };
-	const Cost Cost::var =       Cost{  0,  0,  0,  0,  1,  0,  0 };
-	const Cost Cost::spec =      Cost{  0,  0,  0,  0,  0, -1,  0 };
-	const Cost Cost::reference = Cost{  0,  0,  0,  0,  0,  0,  1 };
-#endif
 
 #if 0
@@ -47,155 +31,4 @@
 #define PRINT(x)
 #endif
-
-	Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue,
-			const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
-		if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
-			PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
-			if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
-				if ( eqvClass->type ) {
-					return conversionCost( src, eqvClass->type, srcIsLvalue, indexer, env );
-				} else {
-					return Cost::infinity;
-				}
-			} else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
-				PRINT( std::cerr << " found" << std::endl; )
-				const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
-				// all typedefs should be gone by this point
-				assert( type );
-				if ( type->base ) {
-					return conversionCost( src, type->base, srcIsLvalue, indexer, env )
-						+ Cost::safe;
-				} // if
-			} // if
-			PRINT( std::cerr << " not found" << std::endl; )
-		} // if
-		PRINT(
-			std::cerr << "src is ";
-			src->print( std::cerr );
-			std::cerr << std::endl << "dest is ";
-			dest->print( std::cerr );
-			std::cerr << std::endl << "env is" << std::endl;
-			env.print( std::cerr, 8 );
-		)
-		if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
-			PRINT( std::cerr << "compatible!" << std::endl; )
-			return Cost::zero;
-		} else if ( dynamic_cast< const VoidType * >( dest ) ) {
-			return Cost::safe;
-		} else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
-			PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
-			return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * const t1, const Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
-				return ptrsAssignable( t1, t2, env );
-			});
-		} else {
-			PassVisitor<ConversionCost> converter(
-				dest, srcIsLvalue, indexer, env,
-				(Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
-					conversionCost );
-			src->accept( converter );
-			if ( converter.pass.get_cost() == Cost::infinity ) {
-				return Cost::infinity;
-			} else {
-				return converter.pass.get_cost() + Cost::zero;
-			} // if
-		} // if
-	}
-
-	static Cost convertToReferenceCost( const Type * src, const Type * dest, bool srcIsLvalue,
-			int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
-		PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
-		if ( diff > 0 ) {
-			// TODO: document this
-			Cost cost = convertToReferenceCost(
-				strict_dynamic_cast< const ReferenceType * >( src )->base, dest, srcIsLvalue,
-				diff-1, indexer, env, func );
-			cost.incReference();
-			return cost;
-		} else if ( diff < -1 ) {
-			// TODO: document this
-			Cost cost = convertToReferenceCost(
-				src, strict_dynamic_cast< const ReferenceType * >( dest )->base, srcIsLvalue,
-				diff+1, indexer, env, func );
-			cost.incReference();
-			return cost;
-		} else if ( diff == 0 ) {
-			const ReferenceType * srcAsRef = dynamic_cast< const ReferenceType * >( src );
-			const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
-			if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
-				PRINT( std::cerr << "converting between references" << std::endl; )
-				Type::Qualifiers tq1 = srcAsRef->base->tq;
-				Type::Qualifiers tq2 = destAsRef->base->tq;
-				if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
-					PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
-					if ( tq1 == tq2 ) {
-						// types are the same
-						return Cost::zero;
-					} else {
-						// types are the same, except otherPointer has more qualifiers
-						return Cost::safe;
-					}
-				} else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
-					int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env );
-					PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
-					if ( assignResult > 0 ) {
-						return Cost::safe;
-					} else if ( assignResult < 0 ) {
-						return Cost::unsafe;
-					} // if
-				} // if
-			} else {
-				PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
-				PassVisitor<ConversionCost> converter(
-					dest, srcIsLvalue, indexer, env,
-					(Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
-						conversionCost );
-				src->accept( converter );
-				return converter.pass.get_cost();
-			} // if
-		} else {
-			const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
-			assert( diff == -1 && destAsRef );
-			PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
-			if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
-				PRINT( std::cerr << "converting compatible base type" << std::endl; )
-				if ( srcIsLvalue ) {
-					PRINT(
-						std::cerr << "lvalue to reference conversion" << std::endl;
-						std::cerr << src << " => " << destAsRef << std::endl;
-					)
-					// lvalue-to-reference conversion:  cv lvalue T => cv T &
-					if ( src->tq == destAsRef->base->tq ) {
-						return Cost::reference; // cost needs to be non-zero to add cast
-					} if ( src->tq < destAsRef->base->tq ) {
-						return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
-					} else {
-						return Cost::unsafe;
-					} // if
-				} else if ( destAsRef->base->get_const() ) {
-					PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
-					// rvalue-to-const-reference conversion: T => const T &
-					return Cost::safe;
-				} else {
-					PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; )
-					// rvalue-to-reference conversion: T => T &
-					return Cost::unsafe;
-				} // if
-			} // if
-			PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; )
-		}
-		return Cost::infinity;
-	}
-
-	Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
-			const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
-		int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
-		Cost cost = convertToReferenceCost( src, dest, srcIsLvalue, sdepth-ddepth, indexer, env, func );
-		PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; )
-		return cost;
-	}
-
-	ConversionCost::ConversionCost( const Type * dest, bool srcIsLvalue, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
-		: dest( dest ), srcIsLvalue( srcIsLvalue ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
-	}
 
 	// GENERATED START, DO NOT EDIT
@@ -319,196 +152,9 @@
 	);
 
-	void ConversionCost::postvisit( const VoidType * ) {
-		cost = Cost::infinity;
-	}
-
-	// refactor for code resue
-	void ConversionCost::conversionCostFromBasicToBasic(const BasicType * src, const BasicType * dest) {
-		int tableResult = costMatrix[ src->kind ][ dest->kind ];
-		if ( tableResult == -1 ) {
-			cost = Cost::unsafe;
-		} else {
-			cost = Cost::zero;
-			cost.incSafe( tableResult );
-			cost.incSign( signMatrix[ src->kind ][ dest->kind ] );
-		} // if
-	} // ConversionCost::conversionCostFromBasicToBasic
-
-	void ConversionCost::postvisit(const BasicType * basicType) {
-		if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
-			conversionCostFromBasicToBasic(basicType, destAsBasic);
-		} else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * >( dest ) ) {
-			const EnumDecl * base_enum = enumInst->baseEnum;
-			if ( const Type * base = base_enum->base ) {
-				if ( const BasicType * enumBaseAstBasic = dynamic_cast< const BasicType *> (base) ) {
-					conversionCostFromBasicToBasic(basicType, enumBaseAstBasic);
-				} else {
-					cost = Cost::infinity;
-				} // if
-			} else {
-				cost = Cost::unsafe;
-			} // if
-		} // if
-		// no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
-	}
-
-	void ConversionCost::postvisit( const PointerType * pointerType ) {
-		if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
-			PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
-			Type::Qualifiers tq1 = pointerType->base->tq;
-			Type::Qualifiers tq2 = destAsPtr->base->tq;
-			if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
-				PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
-				if ( tq1 == tq2 ) {
-					// types are the same
-					cost = Cost::zero;
-				} else {
-					// types are the same, except otherPointer has more qualifiers
-					cost = Cost::safe;
-				} // if
-			} else {
-				int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
-				PRINT( std::cerr << " :: " << assignResult << std::endl; )
-				if ( assignResult > 0 && tq1 <= tq2 ) {
-					// xxx - want the case where qualifiers are added to be more expensive than the case where qualifiers are the same. Is 1 safe vs. 2 safe correct?
-					if ( tq1 == tq2 ) {
-						cost = Cost::safe;
-					} else if ( tq1 < tq2 ) {
-						cost = Cost::safe+Cost::safe;
-					}
-				} else if ( assignResult < 0 ) {
-					cost = Cost::unsafe;
-				} // if
-				// assignResult == 0 means Cost::Infinity
-			} // if
-			// case case for zero_t because it should not be possible to convert pointers to zero_t.
-		} // if
-	}
-
-	void ConversionCost::postvisit( const ArrayType * ) {}
-
-	void ConversionCost::postvisit( const ReferenceType * refType ) {
-		// Note: dest can never be a reference, since it would have been caught in an earlier check
-		assert( ! dynamic_cast< const ReferenceType * >( dest ) );
-		// convert reference to rvalue: cv T1 & => T2
-		// recursively compute conversion cost from T1 to T2.
-		// cv can be safely dropped because of 'implicit dereference' behavior.
-		cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env );
-		if ( refType->base->tq == dest->tq ) {
-			cost.incReference();  // prefer exact qualifiers
-		} else if ( refType->base->tq < dest->tq ) {
-			cost.incSafe(); // then gaining qualifiers
-		} else {
-			cost.incUnsafe(); // lose qualifiers as last resort
-		}
-		PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
-	}
-
-	void ConversionCost::postvisit( const FunctionType * ) {}
-
-	void ConversionCost::postvisit( const EnumInstType * enumInst) {
-		const EnumDecl * enumDecl = enumInst -> baseEnum;
-		if ( const Type * enumType = enumDecl -> base ) { // if it is a typed enum
-			cost = costFunc( enumType, dest, srcIsLvalue, indexer, env );
-		} else {
-			static Type::Qualifiers q;
-			static BasicType integer( q, BasicType::SignedInt );
-			cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
-		} // if
-		if ( cost < Cost::unsafe ) {
-				cost.incSafe();
-		} // if
-	}
-
-	void ConversionCost::postvisit( const TraitInstType * ) {}
-
-	void ConversionCost::postvisit( const TypeInstType * inst ) {
-		if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
-			cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
-		} else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
-			if ( inst->name == destAsInst->name ) {
-				cost = Cost::zero;
-			}
-		} else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
-			const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
-			// all typedefs should be gone by this point
-			assert( type );
-			if ( type->base ) {
-				cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
-			} // if
-		} // if
-	}
-
-	void ConversionCost::postvisit( const TupleType * tupleType ) {
-		Cost c = Cost::zero;
-		if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
-			std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
-			std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
-			while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
-				Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
-				if ( newCost == Cost::infinity ) {
-					return;
-				} // if
-				c += newCost;
-			} // while
-			if ( destIt != destAsTuple->types.end() ) {
-				cost = Cost::infinity;
-			} else {
-				cost = c;
-			} // if
-		} // if
-	}
-
-	void ConversionCost::postvisit( const VarArgsType * ) {
-		if ( dynamic_cast< const VarArgsType * >( dest ) ) {
-			cost = Cost::zero;
-		}
-	}
-
-	void ConversionCost::postvisit( const ZeroType * ) {
-		if ( dynamic_cast< const ZeroType * >( dest ) ) {
-			cost = Cost::zero;
-		} else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
-			// copied from visit(BasicType *) for signed int, but +1 for safe conversions
-			int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
-			if ( tableResult == -1 ) {
-				cost = Cost::unsafe;
-			} else {
-				cost = Cost::zero;
-				cost.incSafe( tableResult + 1 );
-				cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
-			} // if
-		} else if ( dynamic_cast< const PointerType * >( dest ) ) {
-			cost = Cost::zero;
-			cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
-		} // if
-	}
-
-	void ConversionCost::postvisit( const OneType * ) {
-		if ( dynamic_cast< const OneType * >( dest ) ) {
-			cost = Cost::zero;
-		} else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
-			// copied from visit(BasicType *) for signed int, but +1 for safe conversions
-			int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
-			if ( tableResult == -1 ) {
-				cost = Cost::unsafe;
-			} else {
-				cost = Cost::zero;
-				cost.incSafe( tableResult + 1 );
-				cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
-			} // if
-		} // if
-	}
-
 namespace {
-	# warning For overload resolution between the two versions.
 	int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
 			const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
 		return ptrsAssignable( t1, t2, env );
 	}
-	Cost localConversionCost(
-		const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
-		const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
-	) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); }
 }
 
@@ -540,5 +186,5 @@
 		return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
 	} else {
-		return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost );
+		return ast::Pass<ConversionCost>::read( src, dst, srcIsLvalue, symtab, env, conversionCost );
 	}
 }
@@ -581,5 +227,5 @@
 			}
 		} else {
-			return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost );
+			return ast::Pass<ConversionCost>::read( src, dst, srcIsLvalue, symtab, env, conversionCost );
 		}
 	} else {
@@ -613,10 +259,10 @@
 }
 
-void ConversionCost_new::postvisit( const ast::VoidType * voidType ) {
+void ConversionCost::postvisit( const ast::VoidType * voidType ) {
 	(void)voidType;
 	cost = Cost::infinity;
 }
 
-void ConversionCost_new::conversionCostFromBasicToBasic( const ast::BasicType * src, const ast::BasicType* dest ) {
+void ConversionCost::conversionCostFromBasicToBasic( const ast::BasicType * src, const ast::BasicType* dest ) {
 	int tableResult = costMatrix[ src->kind ][ dest->kind ];
 	if ( tableResult == -1 ) {
@@ -629,5 +275,5 @@
 }
 
-void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
+void ConversionCost::postvisit( const ast::BasicType * basicType ) {
 	if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
 		conversionCostFromBasicToBasic( basicType, dstAsBasic );
@@ -635,5 +281,5 @@
 		const ast::EnumDecl * enumDecl = enumInst->base.get();
 		if ( enumDecl->isTyped && !enumDecl->base.get() ) {
-			cost = Cost::infinity; 
+			cost = Cost::infinity;
 		} else if ( const ast::Type * enumType = enumDecl->base.get() ) {
 			if ( const ast::BasicType * enumTypeAsBasic = dynamic_cast<const ast::BasicType *>(enumType) ) {
@@ -648,5 +294,5 @@
 }
 
-void ConversionCost_new::postvisit( const ast::PointerType * pointerType ) {
+void ConversionCost::postvisit( const ast::PointerType * pointerType ) {
 	if ( const ast::PointerType * dstAsPtr = dynamic_cast< const ast::PointerType * >( dst ) ) {
 		ast::CV::Qualifiers tq1 = pointerType->base->qualifiers;
@@ -694,9 +340,9 @@
 }
 
-void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) {
+void ConversionCost::postvisit( const ast::ArrayType * arrayType ) {
 	(void)arrayType;
 }
 
-void ConversionCost_new::postvisit( const ast::ReferenceType * refType ) {
+void ConversionCost::postvisit( const ast::ReferenceType * refType ) {
 	assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
 
@@ -716,9 +362,9 @@
 }
 
-void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) {
+void ConversionCost::postvisit( const ast::FunctionType * functionType ) {
 	(void)functionType;
 }
 
-void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
+void ConversionCost::postvisit( const ast::EnumInstType * enumInstType ) {
 	const ast::EnumDecl * baseEnum = enumInstType->base;
 	if ( const ast::Type * baseType = baseEnum->base ) {
@@ -733,9 +379,9 @@
 }
 
-void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) {
+void ConversionCost::postvisit( const ast::TraitInstType * traitInstType ) {
 	(void)traitInstType;
 }
 
-void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
+void ConversionCost::postvisit( const ast::TypeInstType * typeInstType ) {
 	if ( const ast::EqvClass * eqv = env.lookup( *typeInstType ) ) {
 		cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env );
@@ -754,5 +400,5 @@
 }
 
-void ConversionCost_new::postvisit( const ast::TupleType * tupleType ) {
+void ConversionCost::postvisit( const ast::TupleType * tupleType ) {
 	Cost c = Cost::zero;
 	if ( const ast::TupleType * dstAsTuple = dynamic_cast< const ast::TupleType * >( dst ) ) {
@@ -776,5 +422,5 @@
 }
 
-void ConversionCost_new::postvisit( const ast::VarArgsType * varArgsType ) {
+void ConversionCost::postvisit( const ast::VarArgsType * varArgsType ) {
 	(void)varArgsType;
 	if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) {
@@ -783,5 +429,5 @@
 }
 
-void ConversionCost_new::postvisit( const ast::ZeroType * zeroType ) {
+void ConversionCost::postvisit( const ast::ZeroType * zeroType ) {
 	(void)zeroType;
 	if ( dynamic_cast< const ast::ZeroType * >( dst ) ) {
@@ -810,10 +456,10 @@
 }
 
-void ConversionCost_new::postvisit( const ast::OneType * oneType ) {
+void ConversionCost::postvisit( const ast::OneType * oneType ) {
 	(void)oneType;
 	if ( dynamic_cast< const ast::OneType * >( dst ) ) {
 		cost = Cost::zero;
 	} else if ( const ast::BasicType * dstAsBasic =
-			dynamic_cast< const ast::BasicType * >( dst ) ) {		
+			dynamic_cast< const ast::BasicType * >( dst ) ) {
 		int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
 		if ( -1 == tableResult ) {
@@ -824,9 +470,8 @@
 			cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
 		}
-		
-		// cost = Cost::zero;
-	}
-}
-// size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
+	}
+}
+
+// size_t ConversionCost::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
 
 } // namespace ResolvExpr
Index: src/ResolvExpr/ConversionCost.h
===================================================================
--- src/ResolvExpr/ConversionCost.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/ConversionCost.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -22,59 +22,6 @@
 #include "AST/Fwd.hpp"
 #include "AST/Pass.hpp"       // for WithShortCircuiting
-#include "Common/PassVisitor.h"
-#include "SynTree/Visitor.h"  // for Visitor
-#include "SynTree/SynTree.h"  // for Visitor Nodes
-
-namespace SymTab {
-	class Indexer;
-}  // namespace SymTab
 
 namespace ResolvExpr {
-	class TypeEnvironment;
-
-	Cost conversionCost(
-		const Type * src, const Type * dest, bool srcIsLvalue,
-		const SymTab::Indexer & indexer, const TypeEnvironment & env );
-
-	typedef std::function<Cost(const Type *, const Type *, bool,
-		const SymTab::Indexer &, const TypeEnvironment &)> CostFunction;
-
-	struct ConversionCost : public WithShortCircuiting {
-	  public:
-		ConversionCost( const Type * dest, bool srcIsLvalue,
-			const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction );
-
-		Cost get_cost() const { return cost; }
-
-		void previsit( const BaseSyntaxNode * ) { visit_children = false; }
-
-		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 EnumInstType * aggregateUseType );
-		void postvisit( const TraitInstType * aggregateUseType );
-		void postvisit( const TypeInstType * aggregateUseType );
-		void postvisit( const TupleType * tupleType );
-		void postvisit( const VarArgsType * varArgsType );
-		void postvisit( const ZeroType * zeroType );
-		void postvisit( const OneType * oneType );
-	  protected:
-		const Type * dest;
-		bool srcIsLvalue;
-		const SymTab::Indexer &indexer;
-		Cost cost;
-		const TypeEnvironment &env;
-		CostFunction costFunc;
-	  private:
-	  	// refactor for code resue
-	  	void conversionCostFromBasicToBasic( const BasicType * src, const BasicType* dest );
-	};
-
-	typedef std::function<int(const Type *, const Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction;
-	Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
-		const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
 
 // Some function pointer types, differ in return type.
@@ -92,6 +39,5 @@
 	PtrsCalculation func );
 
-#warning when the old ConversionCost is removed, get ride of the _new suffix.
-class ConversionCost_new : public ast::WithShortCircuiting {
+class ConversionCost : public ast::WithShortCircuiting {
 protected:
 	const ast::Type * dst;
@@ -105,5 +51,5 @@
 	Cost result() { return cost; }
 
-	ConversionCost_new( const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
+	ConversionCost( const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
 			const ast::TypeEnvironment & env, CostCalculation costCalc ) :
 		dst( dst ), srcIsLvalue( srcIsLvalue ), symtab( symtab ), env( env ),
Index: src/ResolvExpr/CurrentObject.cc
===================================================================
--- src/ResolvExpr/CurrentObject.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/CurrentObject.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -33,10 +33,4 @@
 #include "Common/utility.h"            // for toString
 #include "CurrentObject.h"
-#include "SynTree/Constant.h"          // for Constant
-#include "SynTree/Declaration.h"       // for ObjectDecl, Declaration, Struc...
-#include "SynTree/Expression.h"        // for InitAlternative, VariableExpr
-#include "SynTree/Initializer.h"       // for Designation, operator<<
-#include "SynTree/Type.h"              // for Type, StructInstType, UnionIns...
-#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
 
 #if 0
@@ -45,550 +39,4 @@
 #define PRINT(x)
 #endif
-
-namespace ResolvExpr {
-	template< typename AggrInst >
-	TypeSubstitution makeGenericSubstitution( AggrInst * inst ) {
-		assert( inst );
-		assert( inst->get_baseParameters() );
-		std::list< TypeDecl * > baseParams = *inst->get_baseParameters();
-		std::list< Expression * > typeSubs = inst->get_parameters();
-		TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
-		return subs;
-	}
-
-	TypeSubstitution makeGenericSubstitution( Type * type ) {
-		if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) {
-			return makeGenericSubstitution( inst );
-		} else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) {
-			return makeGenericSubstitution( inst );
-		} else {
-			return TypeSubstitution();
-		}
-	}
-
-	class MemberIterator {
-	public:
-		virtual ~MemberIterator() {}
-
-		/// walks the current object using the given designators as a guide
-		virtual void setPosition( std::list< Expression * > & designators ) = 0;
-
-		/// retrieve the list of possible Type/Designation pairs for the current position in the currect object
-		virtual std::list<InitAlternative> operator*() const = 0;
-
-		/// true if the iterator is not currently at the end
-		virtual operator bool() const = 0;
-
-		/// moves the iterator by one member in the current object
-		virtual MemberIterator & bigStep() = 0;
-
-		/// moves the iterator by one member in the current subobject
-		virtual MemberIterator & smallStep() = 0;
-
-		/// the type of the current object
-		virtual Type * getType() = 0;
-
-		/// the type of the current subobject
-		virtual Type * getNext() = 0;
-
-		/// printing for debug
-		virtual void print( std::ostream & out, Indenter indent ) const = 0;
-
-		/// helper for operator*; aggregates must add designator to each init alternative, but
-		/// adding designators in operator* creates duplicates.
-		virtual std::list<InitAlternative> first() const = 0; // should be protected
-	};
-
-	std::ostream & operator<<(std::ostream & out, const MemberIterator & it) {
-		Indenter indenter;
-		it.print( out, indenter );
-		return out;
-	}
-
-	/// create a new MemberIterator that traverses a type correctly
-	MemberIterator * createMemberIterator( Type * type );
-
-	/// iterates "other" types, e.g. basic types, pointer types, etc. which do not change at list initializer entry
-	class SimpleIterator : public MemberIterator {
-	public:
-		SimpleIterator( Type * type ) : type( type ) {}
-
-		virtual void setPosition( std::list< Expression * > & designators ) {
-			assertf( designators.empty(), "simple iterator given non-empty designator..." ); // xxx - might be semantic error
-		}
-
-		virtual std::list<InitAlternative> operator*() const { return first(); }
-		virtual operator bool() const { return type; }
-
-		// big step is the same as small step
-		virtual MemberIterator & bigStep() { return smallStep(); }
-		virtual MemberIterator & smallStep() {
-			type = nullptr;  // type is nullified on increment since SimpleIterators do not have members
-			return *this;
-		}
-
-		virtual void print( std::ostream & out, __attribute__((unused)) Indenter indent ) const {
-			out << "SimpleIterator(" << type << ")";
-		}
-
-		virtual Type * getType() { return type; }
-		virtual Type * getNext() { return type; }
-
-	protected:
-		virtual std::list<InitAlternative> first() const {
-			if ( type ) return std::list<InitAlternative>{ { type->clone(), new Designation( {} ) } };
-			else return std::list<InitAlternative>{};
-		}
-	private:
-		Type * type = nullptr;
-	};
-
-	class ArrayIterator : public MemberIterator {
-	public:
-		ArrayIterator( ArrayType * at ) : array( at ) {
-			PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
-			base = at->base;
-			memberIter = createMemberIterator( base );
-			if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=: " );
-			setSize( at->dimension );
-		}
-
-		~ArrayIterator() {
-			delete memberIter;
-		}
-
-	private:
-		void setSize( Expression * expr ) {
-			auto res = eval( expr );
-			if (res.second) {
-				size = res.first;
-			} else {
-				SemanticError( expr->location, toString("Array designator must be a constant expression: ", expr) );
-			}
-		}
-
-	public:
-		void setPosition( Expression * expr ) {
-			// need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions
-			auto arg = eval( expr );
-			index = arg.first;
-			return;
-
-			// if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
-			// 	try {
-			// 		index = constExpr->intValue();
-			// 	} catch( SemanticErrorException & ) {
-			// 		SemanticError( expr, "Constant expression of non-integral type in array designator: " );
-			// 	}
-			// } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
-			// 	setPosition( castExpr->get_arg() );
-			// } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
-			// 	EnumInstType * inst = dynamic_cast<EnumInstType *>( varExpr->get_result() );
-			// 	assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() );
-			// 	long long int value;
-			// 	if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
-			// 		index = value;
-			// 	}
-			// } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) {
-			// 	index = 0; // xxx - get actual sizeof/alignof value?
-			// } else {
-			// 	assertf( false, "4 bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
-			// }
-		}
-
-		virtual void setPosition( std::list< Expression * > & designators ) {
-			if ( ! designators.empty() ) {
-				setPosition( designators.front() );
-				designators.pop_front();
-				memberIter->setPosition( designators );
-			}
-		}
-
-		virtual std::list<InitAlternative> operator*() const {
-			return first();
-		}
-
-		virtual operator bool() const { return index < size; }
-
-		virtual MemberIterator & bigStep() {
-			PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
-			++index;
-			delete memberIter;
-			if ( index < size ) memberIter = createMemberIterator( base );
-			else memberIter = nullptr;
-			return *this;
-		}
-
-		virtual MemberIterator & smallStep() {
-			PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
-			if ( memberIter ) {
-				PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
-				memberIter->smallStep();
-				if ( *memberIter ) {
-					PRINT( std::cerr << "has valid member iter" << std::endl; )
-					return *this;
-				}
-			}
-			return bigStep();
-		}
-
-		virtual Type * getType() { return array; }
-		virtual Type * getNext() { return base; }
-
-		virtual std::list<InitAlternative> first() const {
-			PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
-			if ( memberIter && *memberIter ) {
-				std::list<InitAlternative> ret = memberIter->first();
-				for ( InitAlternative & alt : ret ) {
-					alt.designation->get_designators().push_front( new ConstantExpr( Constant::from_ulong( index ) ) );
-				}
-				return ret;
-			}
-			return std::list<InitAlternative>();
-		}
-
-		virtual void print( std::ostream & out, Indenter indent ) const {
-			out << "ArrayIterator(Array of " << base << ")";
-			if ( memberIter ) {
-				Indenter childIndent = indent+1;
-				out << std::endl << childIndent;
-				memberIter->print( out, childIndent );
-			}
-		}
-
-	private:
-		ArrayType * array = nullptr;
-		Type * base = nullptr;
-		size_t index = 0;
-		size_t size = 0;
-		MemberIterator * memberIter = nullptr;
-	};
-
-	class AggregateIterator : public MemberIterator {
-	public:
-		typedef std::list<Declaration *> MemberList;
-		typedef MemberList::const_iterator iterator;
-		std::string kind = ""; // for debug
-		std::string name;
-		Type * inst = nullptr;
-		const MemberList & members;
-		iterator curMember;
-		bool atbegin = true; // false at first {small,big}Step -- this aggr type is only added to the possibilities at the beginning
-		Type * curType = nullptr;
-		MemberIterator * memberIter = nullptr;
-		mutable TypeSubstitution sub;
-
-		AggregateIterator( const std::string & kind, const std::string & name, Type * inst, const MemberList & members ) : kind( kind ), name( name ), inst( inst ), members( members ), curMember( members.begin() ), sub( makeGenericSubstitution( inst ) ) {
-			PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
-			init();
-		}
-
-		virtual ~AggregateIterator() {
-			delete memberIter;
-		}
-
-		bool init() {
-			PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
-			if ( curMember != members.end() ) {
-				if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( *curMember ) ) {
-					PRINT( std::cerr << "incremented to field: " << field << std::endl; )
-					curType = field->get_type();
-					memberIter = createMemberIterator( curType );
-					return true;
-				}
-			}
-			return false;
-		}
-
-		virtual std::list<InitAlternative> operator*() const {
-			if (memberIter && *memberIter) {
-				std::list<InitAlternative> ret = memberIter->first();
-				PRINT( std::cerr << "sub: " << sub << std::endl; )
-				for ( InitAlternative & alt : ret ) {
-					PRINT( std::cerr << "iterating and adding designators" << std::endl; )
-					alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) );
-					// need to substitute for generic types, so that casts are to concrete types
-					PRINT( std::cerr << "  type is: " << alt.type; )
-					sub.apply( alt.type ); // also apply to designation??
-					PRINT( std::cerr << " ==> " << alt.type << std::endl; )
-				}
-				return ret;
-			}
-			return std::list<InitAlternative>();
-		}
-
-		virtual void setPosition( std::list< Expression * > & designators ) {
-			if ( ! designators.empty() ) {
-				if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( designators.front() ) ) {
-					for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
-						if ( *curMember == varExpr->get_var() ) {
-							designators.pop_front();
-							delete memberIter;
-							memberIter = createMemberIterator( varExpr->get_result() );
-							curType = varExpr->get_result();
-							atbegin = curMember == members.begin() && designators.empty(); // xxx - is this the right condition for atbegin??
-							memberIter->setPosition( designators );
-							return;
-						} // if
-					} // for
-					assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
-				} else {
-					assertf( false, "3 bad designator given to %s: %s", kind.c_str(), toString( designators.front() ).c_str() );
-				} // if
-			} // if
-		}
-
-		virtual MemberIterator & smallStep() {
-			PRINT( std::cerr << "smallStep in " << kind << std::endl; )
-			atbegin = false;
-			if ( memberIter ) {
-				PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
-				memberIter->smallStep();
-				if ( *memberIter ) {
-					PRINT( std::cerr << "success!" << std::endl; )
-					return *this;
-				}
-			}
-			return bigStep();
-		}
-
-		virtual Type * getType() { return inst; }
-		virtual Type * getNext() {
-			if ( memberIter && *memberIter ) return memberIter->getType(); // xxx - ??? recursive call???
-			return nullptr;
-		}
-
-		virtual std::list<InitAlternative> first() const {
-			std::list<InitAlternative> ret;
-			PRINT( std::cerr << "first " << kind << std::endl; )
-			if ( memberIter && *memberIter ) { // might not need *memberIter??
-				PRINT( std::cerr << "adding children" << std::endl; )
-				ret = memberIter->first();
-				for ( InitAlternative & alt : ret ) {
-					PRINT( std::cerr << "iterating and adding designators" << std::endl; )
-					alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) );
-				}
-			}
-			if ( atbegin ) {
-				// xxx - what about case of empty struct??
-				// only add self if at the very beginning of the structure
-				PRINT( std::cerr << "adding self" << std::endl; )
-				ret.push_front( { inst->clone(), new Designation( {} ) } );
-			}
-			return ret;
-		}
-
-		virtual void print( std::ostream & out, Indenter indent ) const {
-			out << kind << "(" << name << ")";
-			if ( memberIter ) {
-				Indenter childIndent = indent+1;
-				out << std::endl << childIndent;
-				memberIter->print( out, childIndent );
-			}
-		}
-	};
-
-	class UnionIterator : public AggregateIterator {
-	public:
-		UnionIterator( UnionInstType * inst ) : AggregateIterator( "UnionIterator", inst->get_name(), inst, inst->get_baseUnion()->get_members() ) {}
-
-		virtual operator bool() const { return (memberIter && *memberIter); }
-		virtual MemberIterator & bigStep() {
-			// unions only initialize one member
-			PRINT( std::cerr << "bigStep in " << kind << std::endl; )
-			atbegin = false;
-			delete memberIter;
-			memberIter = nullptr;
-			curType = nullptr;
-			curMember = members.end();
-			return *this;
-		}
-	};
-
-	class StructIterator : public AggregateIterator {
-	public:
-		StructIterator( StructInstType * inst ) : AggregateIterator( "StructIterator", inst->get_name(), inst, inst->get_baseStruct()->get_members() ) {}
-
-		virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); }
-
-		virtual MemberIterator & bigStep() {
-			PRINT( std::cerr << "bigStep in " << kind << std::endl; )
-			atbegin = false;
-			delete memberIter;
-			memberIter = nullptr;
-			curType = nullptr;
-			for ( ; curMember != members.end(); ) {
-				++curMember;
-				if ( init() ) {
-					return *this;
-				}
-			}
-			return *this;
-		}
-	};
-
-	class TupleIterator : public AggregateIterator {
-	public:
-		TupleIterator( TupleType * inst ) : AggregateIterator( "TupleIterator", toString("Tuple", inst->size()), inst, inst->get_members() ) {}
-
-		virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); }
-
-		virtual MemberIterator & bigStep() {
-			PRINT( std::cerr << "bigStep in " << kind << std::endl; )
-			atbegin = false;
-			delete memberIter;
-			memberIter = nullptr;
-			curType = nullptr;
-			for ( ; curMember != members.end(); ) {
-				++curMember;
-				if ( init() ) {
-					return *this;
-				}
-			}
-			return *this;
-		}
-	};
-
-	MemberIterator * createMemberIterator( Type * type ) {
-		if ( ReferenceToType * aggr = dynamic_cast< ReferenceToType * >( type ) ) {
-			if ( StructInstType * sit = dynamic_cast< StructInstType * >( aggr ) ) {
-				return new StructIterator( sit );
-			} else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( aggr ) ) {
-				return new UnionIterator( uit );
-			} else {
-				assertf( dynamic_cast< EnumInstType * >( type ) || dynamic_cast< TypeInstType * >( type ), "Encountered unhandled ReferenceToType in createMemberIterator: %s", toString( type ).c_str() );
-				return new SimpleIterator( type );
-			}
-		} else if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
-			return new ArrayIterator( at );
-		} else if ( TupleType * tt = dynamic_cast< TupleType * >( type ) ) {
-			return new TupleIterator( tt );
-		} else {
-			return new SimpleIterator( type );
-		}
-	}
-
-	CurrentObject::CurrentObject() {}
-	CurrentObject::CurrentObject( Type * type ) {
-		objStack.push( new SimpleIterator( type ) );
-	}
-
-
-	void CurrentObject::setNext( Designation * designation ) {
-		assertf( ! objStack.empty(), "obj stack empty in setNext" );
-		PRINT( std::cerr << "____setNext" << designation << std::endl; )
-		objStack.top()->setPosition( designation->get_designators() );
-	}
-
-	Designation * CurrentObject::findNext( Designation * designation ) {
-		typedef std::list< Expression * > DesignatorChain;
-		PRINT( std::cerr << "___findNext" << std::endl; )
-		// find all the d's
-		std::list<DesignatorChain> desigAlts{ { } }, newDesigAlts;
-		std::list<Type *> curTypes { (objStack.top())->getType() }, newTypes;
-		for ( Expression * expr : designation->get_designators() ) {
-			PRINT( std::cerr << "____untyped: " << expr << std::endl; )
-			std::list<DesignatorChain>::iterator dit = desigAlts.begin();
-			if ( NameExpr * nexpr = dynamic_cast<NameExpr *>(expr) ) {
-				for ( Type * t : curTypes ) {
-					assert( dit != desigAlts.end() );
-					DesignatorChain & d = *dit;
-					PRINT( std::cerr << "____actual: " << t << std::endl; )
-					ReferenceToType * refType = dynamic_cast<ReferenceToType *>(t);
-					std::list<Declaration *> members;
-					if ( refType ) {
-						refType->lookup( nexpr->get_name(), members ); // concatenate identical field name
-						// xxx - need to also include anonymous members in this somehow...
-						for ( Declaration * mem: members ) {
-							if ( ObjectDecl * field = dynamic_cast<ObjectDecl *>(mem) ) {
-								PRINT( std::cerr << "____alt: " << field->get_type() << std::endl; )
-								DesignatorChain newD = d;
-								newD.push_back( new VariableExpr( field ) );
-								newDesigAlts.push_back( newD );
-								newTypes.push_back( field->get_type() );
-							} // if
-						} // for
-					} // if
-					++dit;
-				} // for
-			} else {
-				for ( Type * t : curTypes ) {
-					assert( dit != desigAlts.end() );
-					DesignatorChain & d = *dit;
-					if ( ArrayType * at = dynamic_cast< ArrayType * > ( t ) ) {
-						PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
-						d.push_back( expr );
-						newDesigAlts.push_back( d );
-						newTypes.push_back( at->get_base() );
-					}
-					++dit;
-				} // for
-			} // if
-			desigAlts = newDesigAlts;
-			newDesigAlts.clear();
-			curTypes = newTypes;
-			newTypes.clear();
-			assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
-		} // for
-		if ( desigAlts.size() > 1 ) {
-			SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
-		} else if ( desigAlts.size() == 0 ) {
-			SemanticError( designation, "No reasonable alternatives for designation: " );
-		}
-		DesignatorChain & d = desigAlts.back();
-		PRINT( for ( Expression * expr : d ) {
-			std::cerr << "____desig: " << expr << std::endl;
-		} ) // for
-		assertf( ! curTypes.empty(), "empty designator chosen");
-
-		// set new designators
-		assertf( ! objStack.empty(), "empty object stack when setting designation" );
-		Designation * actualDesignation = new Designation( d );
-		objStack.top()->setPosition( d ); // destroys d
-		return actualDesignation;
-	}
-
-	void CurrentObject::increment() {
-		PRINT( std::cerr << "____increment" << std::endl; )
-		if ( ! objStack.empty() ) {
-			PRINT( std::cerr << *objStack.top() << std::endl; )
-			objStack.top()->smallStep();
-		}
-	}
-
-	void CurrentObject::enterListInit() {
-		PRINT( std::cerr << "____entering list init" << std::endl; )
-		assertf( ! objStack.empty(), "empty obj stack entering list init" );
-		Type * type = objStack.top()->getNext();
-		if ( type ) {
-			objStack.push( createMemberIterator( type ) );
-		} else {
-			assertf( false, "not sure about this case..." );
-		}
-	}
-
-	void CurrentObject::exitListInit() {
-		PRINT( std::cerr << "____exiting list init" << std::endl; )
-		assertf( ! objStack.empty(), "objstack empty" );
-		delete objStack.top();
-		objStack.pop();
-		if ( ! objStack.empty() ) {
-			PRINT( std::cerr << *objStack.top() << std::endl; )
-			objStack.top()->bigStep();
-		}
-	}
-
-	std::list< InitAlternative > CurrentObject::getOptions() {
-		PRINT( std::cerr << "____getting current options" << std::endl; )
-		assertf( ! objStack.empty(), "objstack empty in getOptions" );
-		return **objStack.top();
-	}
-
-	Type * CurrentObject::getCurrentType() {
-		PRINT( std::cerr << "____getting current type" << std::endl; )
-		assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
-		return objStack.top()->getNext();
-	}
-} // namespace ResolvExpr
 
 namespace ast {
Index: c/ResolvExpr/ExplodedActual.cc
===================================================================
--- src/ResolvExpr/ExplodedActual.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,31 +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.
-//
-// ExplodedActual.cc --
-//
-// Author           : Aaron B. Moss
-// Created On       : Tue Nov 22 17:06:00 2017
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Tue Nov 22 17:06:00 2017
-// Update Count     : 1
-//
-
-#include "ExplodedActual.h"
-
-#include "Tuples/Explode.h"   // for Tuples::explode
-
-namespace ResolvExpr {
-	ExplodedActual::ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer ) 
-			: env(actual.env), cost(actual.cost), exprs() {
-		Tuples::explode( actual, indexer, *this );
-	}
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ResolvExpr/ExplodedActual.h
===================================================================
--- src/ResolvExpr/ExplodedActual.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,44 +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.
-//
-// ExplodedActual.h --
-//
-// Author           : Aaron B. Moss
-// Created On       : Tue Nov 22 17:06:00 2017
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Tue Nov 22 17:06:00 2017
-// Update Count     : 1
-//
-
-#pragma once
-
-#include <memory>
-#include <vector>
-
-#include "Alternative.h"      // for Alternative, AltList
-#include "Cost.h"             // for Cost
-#include "TypeEnvironment.h"  // for TypeEnvironment
-#include "SymTab/Indexer.h"   // for Indexer
-
-namespace ResolvExpr {
-	/// Pre-exploded actual
-	struct ExplodedActual {
-		TypeEnvironment env;
-		Cost cost;
-		std::vector< std::unique_ptr<Expression> > exprs;
-
-		ExplodedActual() : env(), cost(Cost::zero), exprs() {}
-		ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer );
-		ExplodedActual(ExplodedActual&&) = default;
-		ExplodedActual& operator= (ExplodedActual&&) = default;
-	};
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/ResolvExpr/FindOpenVars.cc
===================================================================
--- src/ResolvExpr/FindOpenVars.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/FindOpenVars.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,89 +16,14 @@
 #include "FindOpenVars.h"
 
-#include <list>                   // for _List_const_iterator, list<>::const...
-#include <map>                    // for map<>::mapped_type
-
 #include "AST/Pass.hpp"
 #include "AST/Type.hpp"
 #include "AST/TypeEnvironment.hpp"
-#include "Common/PassVisitor.h"
-#include "SynTree/Declaration.h"  // for TypeDecl, DeclarationWithType (ptr ...
-#include "SynTree/Type.h"         // for Type, Type::ForallList, ArrayType
 
 #include <iostream>
 
 namespace ResolvExpr {
-	struct FindOpenVars_old : public WithGuards {
-		FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
-
-		void previsit( const PointerType * pointerType );
-		void previsit( const ArrayType * arrayType );
-		void previsit( const FunctionType * functionType );
-		void previsit( const TupleType * tupleType );
-
-		void common_action( const Type *type );
-
-		OpenVarSet &openVars, &closedVars;
-		AssertionSet &needAssertions, &haveAssertions;
-		bool nextIsOpen;
-	};
-
-	void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
-		PassVisitor<FindOpenVars_old> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
-		type->accept( finder );
-	}
-
-	FindOpenVars_old::FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )
-		: openVars( openVars ), closedVars( closedVars ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), nextIsOpen( firstIsOpen )	{
-	}
-
-	void FindOpenVars_old::common_action( const Type * type ) {
-		if ( nextIsOpen ) {
-			for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
-				openVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
-				for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
-					needAssertions[ *assert ].isUsed = false;
-				}
-///       cloneAll( (*i)->get_assertions(), needAssertions );
-///       needAssertions.insert( needAssertions.end(), (*i)->get_assertions().begin(), (*i)->get_assertions().end() );
-			}
-		} else {
-			for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
-				closedVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
-				for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
-					haveAssertions[ *assert ].isUsed = false;
-				}
-///       cloneAll( (*i)->get_assertions(), haveAssertions );
-///       haveAssertions.insert( haveAssertions.end(), (*i)->get_assertions().begin(), (*i)->get_assertions().end() );
-			} // for
-		} // if
-///   std::cerr << "type is ";
-///   type->print( std::cerr );
-///   std::cerr << std::endl << "need is" << std::endl;
-///   printAssertionSet( needAssertions, std::cerr );
-///   std::cerr << std::endl << "have is" << std::endl;
-///   printAssertionSet( haveAssertions, std::cerr );
-	}
-
-	void FindOpenVars_old::previsit(const PointerType * pointerType) {
-		common_action( pointerType );
-	}
-
-	void FindOpenVars_old::previsit(const ArrayType * arrayType) {
-		common_action( arrayType );
-	}
-
-	void FindOpenVars_old::previsit(const FunctionType * functionType) {
-		common_action( functionType );
-		nextIsOpen = ! nextIsOpen;
-		GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } );
-	}
-
-	void FindOpenVars_old::previsit(const TupleType * tupleType) {
-		common_action( tupleType );
-	}
 
 	namespace {
-		struct FindOpenVars_new final : public ast::WithGuards {
+		struct FindOpenVars final : public ast::WithGuards {
 			ast::OpenVarSet & open;
 			ast::OpenVarSet & closed;
@@ -108,5 +33,5 @@
 			bool nextIsOpen;
 
-			FindOpenVars_new(
+			FindOpenVars(
 				ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n,
 				ast::AssertionSet & h, ast::TypeEnvironment & env, FirstMode firstIsOpen )
@@ -148,5 +73,5 @@
 			const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,
 			ast::AssertionSet & need, ast::AssertionSet & have, ast::TypeEnvironment & env, FirstMode firstIsOpen ) {
-		ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, env, firstIsOpen };
+		ast::Pass< FindOpenVars > finder{ open, closed, need, have, env, firstIsOpen };
 		type->accept( finder );
 
Index: src/ResolvExpr/FindOpenVars.h
===================================================================
--- src/ResolvExpr/FindOpenVars.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/FindOpenVars.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -17,7 +17,5 @@
 
 #include "AST/TypeEnvironment.hpp"  // for AssertionSet, OpenVarSet
-#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
 
-class Type;
 namespace ast {
 	class Type;
@@ -25,7 +23,4 @@
 
 namespace ResolvExpr {
-	// Updates open and closed variables and their associated assertions
-	void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
-
 	enum FirstMode { FirstClosed, FirstOpen };
 
Index: c/ResolvExpr/Occurs.cc
===================================================================
--- src/ResolvExpr/Occurs.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,68 +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.
-//
-// Occurs.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 09:47:41 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sun May 17 09:49:26 2015
-// Update Count     : 2
-//
-
-#include <set>                // for set, _Rb_tree_const_iterator
-#include <string>             // for string
-
-#include "Common/PassVisitor.h"
-#include "SynTree/Type.h"     // for TypeInstType, Type
-#include "TypeEnvironment.h"  // for EqvClass, TypeEnvironment
-
-namespace ResolvExpr {
-	struct Occurs : public WithVisitorRef<Occurs> {
-		Occurs( std::string varName, const TypeEnvironment &env );
-		void previsit( const TypeInstType * typeInst );
-
-		bool result;
-		std::set< std::string > eqvVars;
-		const TypeEnvironment &tenv;
-	};
-
-	bool occurs( const Type *type, const std::string & varName, const TypeEnvironment &env ) {
-		PassVisitor<Occurs> occur( varName, env );
-		type->accept( occur );
-		return occur.pass.result;
-	}
-
-	Occurs::Occurs( std::string varName, const TypeEnvironment & env ) : result( false ), tenv( env ) {
-		if ( const EqvClass *eqvClass = tenv.lookup( varName ) ) {
-			eqvVars = eqvClass->vars;
-		} else {
-			eqvVars.insert( varName );
-		} // if
-	}
-
-	void Occurs::previsit( const TypeInstType * typeInst ) {
-		///   std::cerr << "searching for vars: ";
-///   std::copy( eqvVars.begin(), eqvVars.end(), std::ostream_iterator< std::string >( std::cerr, " " ) );
-///   std::cerr << std::endl;
-		if ( eqvVars.find( typeInst->get_name() ) != eqvVars.end() ) {
-			result = true;
-		} else if ( const EqvClass *eqvClass = tenv.lookup( typeInst->get_name() ) ) {
-			if ( eqvClass->type ) {
-///       std::cerr << typeInst->get_name() << " is bound to";
-///       eqvClass.type->print( std::cerr );
-///       std::cerr << std::endl;
-				eqvClass->type->accept( *visitor );
-			} // if
-		} // if
-	}
-} // namespace ResolvExpr
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/ResolvExpr/PolyCost.cc
===================================================================
--- src/ResolvExpr/PolyCost.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/PolyCost.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -18,46 +18,8 @@
 #include "AST/Type.hpp"
 #include "AST/TypeEnvironment.hpp"
-#include "Common/PassVisitor.h"
-#include "SymTab/Indexer.h"   // for Indexer
-#include "SynTree/Type.h"     // for TypeInstType, Type
-#include "TypeEnvironment.h"  // for EqvClass, TypeEnvironment
 
 namespace ResolvExpr {
-	struct PolyCost {
-		PolyCost( const TypeEnvironment &env, const SymTab::Indexer &indexer );
 
-		void previsit( TypeInstType * aggregateUseType );
-		int result;
-		const TypeEnvironment &tenv;
-		const SymTab::Indexer &indexer;
-	};
-
-	int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) {
-		PassVisitor<PolyCost> coster( env, indexer );
-		type->accept( coster );
-		return (coster.pass.result > 0) ? 1 : 0;
-	}
-
-	PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), tenv( env ), indexer( indexer ) {
-	}
-
-	void PolyCost::previsit(TypeInstType * typeInst) {
-		if ( const EqvClass *eqvClass = tenv.lookup( typeInst->name ) ) {
-			if ( eqvClass->type ) {
-				if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass->type ) ) {
-					if ( indexer.lookupType( otherTypeInst->name ) ) {
-						// bound to opaque type
-						result += 1;
-					} // if
-				} else {
-					// bound to concrete type
-					result += 1;
-				} // if
-			} // if
-		} // if
-	}
-
-// TODO: When the old PolyCost is torn out get rid of the _new suffix.
-class PolyCost_new {
+class PolyCost {
 	const ast::SymbolTable &symtab;
 public:
@@ -65,5 +27,5 @@
 	const ast::TypeEnvironment &env_;
 
-	PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) 
+	PolyCost( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) 
 	: symtab( symtab ), result( 0 ), env_( env ) {}
 
@@ -86,5 +48,5 @@
 	const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
 ) {
-	ast::Pass<PolyCost_new> costing( symtab, env );
+	ast::Pass<PolyCost> costing( symtab, env );
 	type->accept( costing );
 	return (costing.core.result > 0) ? 1 : 0;
Index: src/ResolvExpr/PolyCost.hpp
===================================================================
--- src/ResolvExpr/PolyCost.hpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/PolyCost.hpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,8 +16,4 @@
 #pragma once
 
-class Type;
-namespace SymTab {
-    class Indexer;
-}
 namespace ast {
     class SymbolTable;
@@ -28,8 +24,4 @@
 namespace ResolvExpr {
 
-class TypeEnvironment;
-
-int polyCost( Type * type,
-	const TypeEnvironment & env, const SymTab::Indexer & indexer );
 int polyCost( const ast::Type * type,
 	const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
Index: src/ResolvExpr/PtrsAssignable.cc
===================================================================
--- src/ResolvExpr/PtrsAssignable.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/PtrsAssignable.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -19,107 +19,16 @@
 #include "AST/Type.hpp"
 #include "AST/TypeEnvironment.hpp"
-#include "Common/PassVisitor.h"
-#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
-#include "SynTree/Type.h"                // for TypeInstType, Type, BasicType
-#include "SynTree/Visitor.h"             // for Visitor
-
 
 namespace ResolvExpr {
-	struct PtrsAssignable : public WithShortCircuiting {
-		PtrsAssignable( const Type * dest, const TypeEnvironment &env );
 
-		int get_result() const { return result; }
-
-		void previsit( const Type * ) { visit_children = false; }
-
-		void postvisit( const VoidType * voidType );
-		void postvisit( const BasicType * basicType );
-		void postvisit( const PointerType * pointerType );
-		void postvisit( const ArrayType * arrayType );
-		void postvisit( const FunctionType * functionType );
-		void postvisit( const StructInstType * inst );
-		void postvisit( const UnionInstType * inst );
-		void postvisit( const EnumInstType * inst );
-		void postvisit( const TraitInstType * inst );
-		void postvisit( const TypeInstType * inst );
-		void postvisit( const TupleType * tupleType );
-		void postvisit( const VarArgsType * varArgsType );
-		void postvisit( const ZeroType * zeroType );
-		void postvisit( const OneType * oneType );
-	  private:
-		const Type * dest;
-		int result;
-		const TypeEnvironment &env;
-	};
-
-	int ptrsAssignable( const Type *src, const Type * dest, const TypeEnvironment &env ) {
-		// std::cerr << "assignable: " << src << " | " << dest << std::endl;
-		if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
-			if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
-				return ptrsAssignable( src, eqvClass->type, env );
-			} // if
-		} // if
-		if ( dynamic_cast< const VoidType* >( dest ) ) {
-			// void * = T * for any T is unsafe
-			// xxx - this should be safe, but that currently breaks the build
-			return -1;
-		} else {
-			PassVisitor<PtrsAssignable> ptrs( dest, env );
-			src->accept( ptrs );
-			return ptrs.pass.get_result();
-		} // if
-	}
-
-	PtrsAssignable::PtrsAssignable( const Type * dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
-
-	void PtrsAssignable::postvisit( const VoidType * ) {
-		// T * = void * is disallowed - this is a change from C, where any
-		// void * can be assigned or passed to a non-void pointer without a cast.
-	}
-
-	void PtrsAssignable::postvisit( const BasicType * ) {}
-	void PtrsAssignable::postvisit( const PointerType * ) {}
-	void PtrsAssignable::postvisit( const ArrayType * ) {}
-	void PtrsAssignable::postvisit( const FunctionType * ) {}
-
-	void PtrsAssignable::postvisit( const StructInstType * ) {}
-	void PtrsAssignable::postvisit( const UnionInstType * ) {}
-
-	void PtrsAssignable::postvisit( const EnumInstType * ) {
-		if ( dynamic_cast< const BasicType* >( dest ) ) {
-			// int * = E *, etc. is safe. This isn't technically correct, as each
-			// enum has one basic type that it is compatible with, an that type can
-			// differ from enum to enum. Without replicating GCC's internal logic,
-			// there is no way to know which type this particular enum is compatible
-			// with, so punt on this for now.
-			result = 1;
-		}
-	}
-
-	void PtrsAssignable::postvisit(  const TraitInstType * ) {}
-	void PtrsAssignable::postvisit( const TypeInstType * inst ) {
-		if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
-			if ( eqvClass->type ) {
-				// T * = S * for any S depends on the type bound to T
-				result = ptrsAssignable( eqvClass->type, dest, env );
-			}
-		} // if
-	}
-
-	void PtrsAssignable::postvisit( const TupleType * ) {}
-	void PtrsAssignable::postvisit( const VarArgsType * ) {}
-	void PtrsAssignable::postvisit( const ZeroType * ) {}
-	void PtrsAssignable::postvisit( const OneType * ) {}
-
-// TODO: Get rid of the `_new` suffix when the old version is removed.
-struct PtrsAssignable_new : public ast::WithShortCircuiting {
+struct PtrsAssignable : public ast::WithShortCircuiting {
 	const ast::Type * dst;
 	const ast::TypeEnvironment & typeEnv;
 	int result;
 
-	PtrsAssignable_new( const ast::Type * dst, const ast::TypeEnvironment & env ) :
+	PtrsAssignable( const ast::Type * dst, const ast::TypeEnvironment & env ) :
 		dst( dst ), typeEnv( env ), result( 0 ) {}
 
-	void previsit( Type * ) { visit_children = false; }
+	void previsit( ast::Type * ) { visit_children = false; }
 
 	void postvisit( const ast::EnumInstType * ) {
@@ -153,5 +62,5 @@
 		return -1;
 	} else {
-		ast::Pass<PtrsAssignable_new> visitor( dst, env );
+		ast::Pass<PtrsAssignable> visitor( dst, env );
 		src->accept( visitor );
 		return visitor.core.result;
Index: src/ResolvExpr/PtrsAssignable.hpp
===================================================================
--- src/ResolvExpr/PtrsAssignable.hpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/PtrsAssignable.hpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,5 +16,4 @@
 #pragma once
 
-class Type;
 namespace ast {
 	class Type;
@@ -24,8 +23,4 @@
 namespace ResolvExpr {
 
-class TypeEnvironment;
-
-int ptrsAssignable( const Type * src, const Type * dest,
-	const TypeEnvironment & env );
 int ptrsAssignable( const ast::Type * src, const ast::Type * dst,
 	const ast::TypeEnvironment & env );
Index: src/ResolvExpr/PtrsCastable.cc
===================================================================
--- src/ResolvExpr/PtrsCastable.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/PtrsCastable.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -20,151 +20,7 @@
 #include "AST/Type.hpp"
 #include "AST/TypeEnvironment.hpp"
-#include "Common/PassVisitor.h"
 #include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
-#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
-#include "SymTab/Indexer.h"              // for Indexer
-#include "SynTree/Declaration.h"         // for TypeDecl, TypeDecl::Kind::Ftype
-#include "SynTree/Type.h"                // for TypeInstType, Type, BasicType
-#include "SynTree/Visitor.h"             // for Visitor
 
 namespace ResolvExpr {
-	struct PtrsCastable_old : public WithShortCircuiting  {
-	  public:
-		PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
-
-		int get_result() const { return result; }
-
-		void previsit( const Type * ) { visit_children = false; }
-
-		void postvisit( const VoidType * voidType );
-		void postvisit( const BasicType * basicType );
-		void postvisit( const PointerType * pointerType );
-		void postvisit( const ArrayType * arrayType );
-		void postvisit( const FunctionType * functionType );
-		void postvisit( const StructInstType * inst );
-		void postvisit( const UnionInstType * inst );
-		void postvisit( const EnumInstType * inst );
-		void postvisit( const TraitInstType * inst );
-		void postvisit( const TypeInstType * inst );
-		void postvisit( const TupleType * tupleType );
-		void postvisit( const VarArgsType * varArgsType );
-		void postvisit( const ZeroType * zeroType );
-		void postvisit( const OneType * oneType );
-	  private:
-		const Type * dest;
-		int result;
-		const TypeEnvironment &env;
-		const SymTab::Indexer &indexer;
-	};
-
-	namespace {
-		int objectCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
-			if ( dynamic_cast< const FunctionType* >( src ) ) {
-				return -1;
-			} else if ( const TypeInstType * typeInst = dynamic_cast< const TypeInstType* >( src ) ) {
-				if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->name ) ) {
-					if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl* >( ntDecl ) ) {
-						if ( tyDecl->kind == TypeDecl::Ftype ) {
-							return -1;
-						} // if
-					} //if
-				} else if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {
-					if ( eqvClass->data.kind == TypeDecl::Ftype ) {
-						return -1;
-					} // if
-				} // if
-			} //if
-			return 1;
-		}
-		int functionCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
-			return -1 * objectCast( src, env, indexer );  // reverse the sense of objectCast
-		}
-	}
-
-	int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
-		if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
-			if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
-				// xxx - should this be ptrsCastable?
-				return ptrsAssignable( src, eqvClass->type, env );
-			} // if
-		} // if
-		if ( dynamic_cast< const VoidType* >( dest ) ) {
-			return objectCast( src, env, indexer );
-		} else {
-			PassVisitor<PtrsCastable_old> ptrs( dest, env, indexer );
-			src->accept( ptrs );
-			return ptrs.pass.get_result();
-		} // if
-	}
-
-	PtrsCastable_old::PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
-		: dest( dest ), result( 0 ), env( env ), indexer( indexer )	{
-	}
-
-	void PtrsCastable_old::postvisit( const VoidType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( const BasicType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( const PointerType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( const ArrayType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( const FunctionType * ) {
-		// result = -1;
-		result = functionCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( const StructInstType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( const UnionInstType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( const EnumInstType * ) {
-		if ( dynamic_cast< const EnumInstType * >( dest ) ) {
-			result = 1;
-		} else if ( const BasicType * bt = dynamic_cast< const BasicType * >( dest ) ) {
-			if ( bt->kind == BasicType::SignedInt ) {
-				result = 0;
-			} else {
-				result = 1;
-			}
-		} else {
-			result = objectCast( dest, env, indexer );
-		}
-	}
-
-	void PtrsCastable_old::postvisit( const TraitInstType * ) {}
-
-	void PtrsCastable_old::postvisit( const TypeInstType *inst ) {
-		//result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1;
-		result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1;
-	}
-
-	void PtrsCastable_old::postvisit( const TupleType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( const VarArgsType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( const ZeroType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( const OneType * ) {
-		result = objectCast( dest, env, indexer );
-	}
 
 namespace {
@@ -199,5 +55,5 @@
 	}
 
-	class PtrsCastable_new : public ast::WithShortCircuiting {
+	class PtrsCastable : public ast::WithShortCircuiting {
 		const ast::Type * dst;
 		const ast::TypeEnvironment & env;
@@ -206,5 +62,5 @@
 		int result;
 
-		PtrsCastable_new(
+		PtrsCastable(
 			const ast::Type * d, const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
 		: dst( d ), env( e ), symtab( syms ), result( 0 ) {}
@@ -293,5 +149,5 @@
 		return objectCast( src, env, symtab );
 	} else {
-		return ast::Pass<PtrsCastable_new>::read( src, dst, env, symtab );
+		return ast::Pass<PtrsCastable>::read( src, dst, env, symtab );
 	}
 }
Index: src/ResolvExpr/PtrsCastable.hpp
===================================================================
--- src/ResolvExpr/PtrsCastable.hpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/PtrsCastable.hpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,8 +16,4 @@
 #pragma once
 
-class Type;
-namespace SymTab {
-    class Indexer;
-}
 namespace ast {
     class SymbolTable;
@@ -28,9 +24,4 @@
 namespace ResolvExpr {
 
-class TypeEnvironment;
-
-int ptrsCastable(
-	const Type * src, const Type * dst,
-	const TypeEnvironment & env, const SymTab::Indexer & indexer );
 int ptrsCastable(
 	const ast::Type * src, const ast::Type * dst,
Index: src/ResolvExpr/RenameVars.cc
===================================================================
--- src/ResolvExpr/RenameVars.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/RenameVars.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -21,12 +21,7 @@
 #include "AST/Pass.hpp"
 #include "AST/Type.hpp"
-#include "Common/PassVisitor.h"
 #include "Common/ScopedMap.h"
 #include "Common/SemanticError.h"  // for SemanticError
 #include "RenameVars.h"
-#include "SynTree/Declaration.h"   // for DeclarationWithType, TypeDecl, Dec...
-#include "SynTree/Expression.h"    // for Expression
-#include "SynTree/Type.h"          // for Type, TypeInstType, TraitInstType
-#include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
 
 #include "AST/Copy.hpp"
@@ -49,35 +44,6 @@
 		}
 
-		void rename( TypeInstType * type ) {
-			auto it = nameMap.find( type->name );
-			if ( it != nameMap.end() ) {
-				type->name = it->second;
-			}
-		}
-
 		void nextUsage() {
 			++next_usage_id;
-		}
-
-		void openLevel( Type * type ) {
-			if ( ! type->forall.empty() ) {
-				nameMap.beginScope();
-				// renames all "forall" type names to `_${level}_${name}'
-				for ( auto td : type->forall ) {
-					std::ostringstream output;
-					output << "_" << resetCount << "_" << level << "_" << td->name;
-					std::string newname( output.str() );
-					nameMap[ td->get_name() ] = newname;
-					td->name = newname;
-					// ditto for assertion names, the next level in
-					level++;
-				}
-			}
-		}
-
-		void closeLevel( Type * type ) {
-			if ( !type->forall.empty() ) {
-				nameMap.endScope();
-			}
 		}
 
@@ -135,18 +101,5 @@
 	RenamingData renaming;
 
-	struct RenameVars_old {
-		void previsit( TypeInstType * instType ) {
-			renaming.openLevel( (Type*)instType );
-			renaming.rename( instType );
-		}
-		void previsit( Type * type ) {
-			renaming.openLevel( type );
-		}
-		void postvisit( Type * type ) {
-			renaming.closeLevel( type );
-		}
-	};
-
-	struct RenameVars_new : public ast::PureVisitor /*: public ast::WithForallSubstitutor*/ {
+	struct RenameVars final : public ast::PureVisitor /*: public ast::WithForallSubstitutor*/ {
 		RenameMode mode;
 
@@ -178,11 +131,6 @@
 } // namespace
 
-void renameTyVars( Type * t ) {
-	PassVisitor<RenameVars_old> renamer;
-	t->accept( renamer );
-}
-
 const ast::Type * renameTyVars( const ast::Type * t, RenameMode mode, bool reset ) {
-	ast::Pass<RenameVars_new> renamer;
+	ast::Pass<RenameVars> renamer;
 	renamer.core.mode = mode;
 	if (mode == GEN_USAGE && reset) {
Index: src/ResolvExpr/RenameVars.h
===================================================================
--- src/ResolvExpr/RenameVars.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/RenameVars.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,11 +16,4 @@
 #pragma once
 
-#include <list>               // for list
-#include <map>                // for map
-#include <string>             // for string
-
-#include "SynTree/SynTree.h"  // for Visitor Nodes
-#include "SynTree/Visitor.h"  // for Visitor
-
 namespace ast {
 	class Type;
@@ -28,7 +21,4 @@
 
 namespace ResolvExpr {
-	/// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID
-	void renameTyVars( Type * );
-
 	enum RenameMode {
 		GEN_USAGE, // for type in VariableExpr
Index: c/ResolvExpr/ResolveAssertions.cc
===================================================================
--- src/ResolvExpr/ResolveAssertions.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,535 +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.
-//
-// ResolveAssertions.cc --
-//
-// Author           : Aaron B. Moss
-// Created On       : Fri Oct 05 13:46:00 2018
-// Last Modified By : Andrew Beach
-// Last Modified On : Thu Aug  8 16:47:00 2019
-// Update Count     : 3
-//
-
-#include "ResolveAssertions.h"
-
-#include <algorithm>                // for sort
-#include <cassert>                  // for assertf
-#include <list>                     // for list
-#include <memory>                   // for unique_ptr
-#include <sstream>                  // for ostringstream
-#include <string>                   // for string
-#include <unordered_map>            // for unordered_map, unordered_multimap
-#include <utility>                  // for move
-#include <vector>                   // for vector
-
-#include "AdjustExprType.hpp"       // for adjustExprType
-#include "Alternative.h"            // for Alternative, AssertionItem, AssertionList
-#include "Common/FilterCombos.h"    // for filterCombos
-#include "Common/Indenter.h"        // for Indenter
-#include "GenPoly/GenPoly.h"        // for getFunctionType
-#include "ResolvExpr/AlternativeFinder.h"  // for computeConversionCost
-#include "ResolvExpr/RenameVars.h"  // for renameTyVars
-#include "SpecCost.hpp"             // for specCost
-#include "SymTab/Indexer.h"         // for Indexer
-#include "SymTab/Mangler.h"         // for Mangler
-#include "SynTree/Expression.h"     // for InferredParams
-#include "TypeEnvironment.h"        // for TypeEnvironment, etc.
-#include "Unify.h"                  // for unify
-
-namespace ResolvExpr {
-	/// Unified assertion candidate
-	struct AssnCandidate {
-		SymTab::Indexer::IdData cdata;  ///< Satisfying declaration
-		Type* adjType;                  ///< Satisfying type
-		TypeEnvironment env;            ///< Post-unification environment
-		AssertionSet have;              ///< Post-unification have-set
-		AssertionSet need;              ///< Post-unification need-set
-		OpenVarSet openVars;            ///< Post-unification open-var set
-		UniqueId resnSlot;              ///< Slot for any recursive assertion IDs
-
-		AssnCandidate( const SymTab::Indexer::IdData& cdata, Type* adjType, TypeEnvironment&& env,
-			AssertionSet&& have, AssertionSet&& need, OpenVarSet&& openVars, UniqueId resnSlot )
-		: cdata(cdata), adjType(adjType), env(std::move(env)), have(std::move(have)),
-			need(std::move(need)), openVars(std::move(openVars)), resnSlot(resnSlot) {}
-	};
-
-	/// List of candidate assertion resolutions
-	using CandidateList = std::vector<AssnCandidate>;
-
-	/// Reference to single deferred item
-	struct DeferRef {
-		const DeclarationWithType* decl;
-		const AssertionSetValue& info;
-		const AssnCandidate& match;
-	};
-
-	/// Wrapper for the deferred items from a single assertion resolution.
-	/// Acts like indexed list of DeferRef
-	struct DeferItem {
-		const DeclarationWithType* decl;
-		const AssertionSetValue& info;
-		CandidateList matches;
-
-		DeferItem( const DeclarationWithType* decl, const AssertionSetValue& info, CandidateList&& matches )
-		: decl(decl), info(info), matches(std::move(matches)) {}
-
-		bool empty() const { return matches.empty(); }
-
-		CandidateList::size_type size() const { return matches.size(); }
-
-		DeferRef operator[] ( unsigned i ) const { return { decl, info, matches[i] }; }
-	};
-
-	/// List of deferred resolution items
-	using DeferList = std::vector<DeferItem>;
-
-	/// Combo iterator that combines candidates into an output list, merging their environments.
-	/// Rejects an appended candidate if the environments cannot be merged.
-	class CandidateEnvMerger {
-		/// Current list of merged candidates
-		std::vector<DeferRef> crnt;
-		/// Stack of environments to support backtracking
-		std::vector<TypeEnvironment> envs;
-		/// Stack of open variables to support backtracking
-		std::vector<OpenVarSet> varSets;
-		/// Indexer to use for merges
-		const SymTab::Indexer& indexer;
-
-	public:
-		/// The merged environment/open variables and the list of candidates
-		struct OutType {
-			TypeEnvironment env;
-			OpenVarSet openVars;
-			std::vector<DeferRef> assns;
-			Cost cost;
-
-			OutType( const TypeEnvironment& env, const OpenVarSet& openVars,
-				const std::vector<DeferRef>& assns )
-			: env(env), openVars(openVars), assns(assns), cost(Cost::infinity) {}
-		};
-
-		CandidateEnvMerger( const TypeEnvironment& env, const OpenVarSet& openVars,
-			const SymTab::Indexer& indexer )
-		: crnt(), envs{ env }, varSets{ openVars }, indexer(indexer) {}
-
-		bool append( DeferRef i ) {
-			TypeEnvironment env = envs.back();
-			OpenVarSet openVars = varSets.back();
-			mergeOpenVars( openVars, i.match.openVars );
-
-			if ( ! env.combine( i.match.env, openVars, indexer ) ) return false;
-
-			crnt.emplace_back( i );
-			envs.emplace_back( env );
-			varSets.emplace_back( openVars );
-			return true;
-		}
-
-		void backtrack() {
-			crnt.pop_back();
-			envs.pop_back();
-			varSets.pop_back();
-		}
-
-		OutType finalize() { return { envs.back(), varSets.back(), crnt }; }
-	};
-
-	/// Comparator for CandidateEnvMerger outputs that sums their costs and caches the stored
-	/// sums
-	struct CandidateCost {
-		using Element = CandidateEnvMerger::OutType;
-	private:
-		const SymTab::Indexer& indexer;  ///< Indexer for costing
-
-	public:
-		CandidateCost( const SymTab::Indexer& indexer ) : indexer(indexer) {}
-
-		/// reports the cost of an element
-		Cost get( Element& x ) const {
-			// check cached cost
-			if ( x.cost != Cost::infinity ) return x.cost;
-
-			// generate cost
-			Cost k = Cost::zero;
-			for ( const auto& assn : x.assns ) {
-				// compute conversion cost from satisfying decl to assertion
-				k += computeConversionCost(
-					assn.match.adjType, assn.decl->get_type(), false, indexer, x.env );
-
-				// mark vars+specialization cost on function-type assertions
-				FunctionType* func = GenPoly::getFunctionType( assn.match.cdata.id->get_type() );
-				if ( ! func ) continue;
-
-				for ( DeclarationWithType* formal : func->parameters ) {
-					k.decSpec( specCost( formal->get_type() ) );
-				}
-				k.incVar( func->forall.size() );
-				for ( TypeDecl* td : func->forall ) {
-					k.decSpec( td->assertions.size() );
-				}
-			}
-
-			// cache and return
-			x.cost = k;
-			return k;
-		}
-
-		/// compares elements by cost
-		bool operator() ( Element& a, Element& b ) const {
-			return get( a ) < get( b );
-		}
-	};
-
-	/// Set of assertion resolutions, grouped by resolution ID
-	using InferCache = std::unordered_map< UniqueId, InferredParams >;
-
-	/// Lexicographically-ordered vector of costs
-	using CostVec = std::vector< Cost >;
-
-	int compare( const CostVec & a, const CostVec & b ) {
-		unsigned i = 0;
-		do {
-			// lex-compare where shorter one is less
-			if ( i == a.size() ) {
-				return i == b.size() ? 0 : -1;
-			}
-			if ( i == b.size() /* && i < a.size() */ ) return 1;
-
-			int c = a[i].compare( b[i] );
-			if ( c != 0 ) return c;
-		} while ( ++i );
-		assert(!"unreachable");
-	}
-
-	bool operator< ( const CostVec & a, const CostVec & b ) { return compare( a, b ) < 0; }
-
-	/// Flag for state iteration
-	enum IterateFlag { IterateState };
-
-	/// State needed to resolve a set of assertions
-	struct ResnState {
-		Alternative alt;           ///< Alternative assertion is rooted on
-		AssertionList need;        ///< Assertions to find
-		AssertionSet newNeed;      ///< New assertions for current resolutions
-		DeferList deferred;        ///< Deferred matches
-		InferCache inferred;       ///< Cache of already-inferred parameters
-		CostVec costs;             ///< Costs of recursive assertion satisfaction for disambiguation
-		SymTab::Indexer& indexer;  ///< Name lookup (depends on previous assertions)
-
-		/// Initial resolution state for an alternative
-		ResnState( Alternative & a, SymTab::Indexer & indexer )
-		: alt(a), need(), newNeed(), deferred(), inferred(), costs{ Cost::zero }, indexer(indexer) {
-			need.swap( a.need );
-		}
-
-		/// Updated resolution state with new need-list
-		ResnState( ResnState && o, IterateFlag )
-		: alt(std::move(o.alt)), need(o.newNeed.begin(), o.newNeed.end()), newNeed(), deferred(),
-		  inferred(std::move(o.inferred)), costs(o.costs), indexer(o.indexer) {
-			costs.emplace_back( Cost::zero );
-		}
-	};
-
-	/// Binds a single assertion, updating resolution state
-	void bindAssertion( const DeclarationWithType * decl, AssertionSetValue info, Alternative & alt,
-			AssnCandidate & match, InferCache & inferred ) {
-
-		const DeclarationWithType * candidate = match.cdata.id;
-		assertf( candidate->uniqueId, "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
-
-		Expression * varExpr = match.cdata.combine( alt.cvtCost );
-		delete varExpr->result;
-		varExpr->result = match.adjType->clone();
-		if ( match.resnSlot ) { varExpr->resnSlots.push_back( match.resnSlot ); }
-
-		// place newly-inferred assertion in proper place in cache
-		inferred[ info.resnSlot ][ decl->get_uniqueId() ] = ParamEntry{
-				candidate->uniqueId, candidate->clone(), match.adjType->clone(), decl->get_type()->clone(),
-				varExpr };
-	}
-
-	/// Adds a captured assertion to the symbol table
-	void addToIndexer( AssertionSet & assertSet, SymTab::Indexer & indexer ) {
-		for ( auto&  i : assertSet ) {
-			if ( i.second.isUsed ) {
-				indexer.addId( i.first );
-			}
-		}
-	}
-
-	// in AlternativeFinder.cc; unique ID for assertion resolutions
-	extern UniqueId globalResnSlot;
-
-	/// Resolve a single assertion, in context
-	bool resolveAssertion( AssertionItem & assn, ResnState & resn ) {
-		// skip unused assertions
-		if ( ! assn.info.isUsed ) return true;
-
-		// lookup candidates for this assertion
-		std::list< SymTab::Indexer::IdData > candidates;
-		resn.indexer.lookupId( assn.decl->name, candidates );
-
-		// find the candidates that unify with the desired type
-		CandidateList matches;
-		for ( const auto & cdata : candidates ) {
-			const DeclarationWithType * candidate = cdata.id;
-
-			// ignore deleted candidates.
-			// NOTE: this behavior is different from main resolver.
-			// further investigations might be needed to determine
-			// if we should implement the same rule here
-			// (i.e. error if unique best match is deleted)
-			if (candidate->isDeleted) continue;
-
-			// build independent unification context. for candidate
-			AssertionSet have, newNeed;
-			TypeEnvironment newEnv{ resn.alt.env };
-			OpenVarSet newOpenVars{ resn.alt.openVars };
-			Type * adjType = candidate->get_type()->clone();
-			adjustExprType( adjType, newEnv, resn.indexer );
-			renameTyVars( adjType );
-
-			// keep unifying candidates
-			if ( unify( assn.decl->get_type(), adjType, newEnv, newNeed, have, newOpenVars,
-					resn.indexer ) ) {
-				// set up binding slot for recursive assertions
-				UniqueId crntResnSlot = 0;
-				if ( ! newNeed.empty() ) {
-					crntResnSlot = ++globalResnSlot;
-					for ( auto& a : newNeed ) {
-						a.second.resnSlot = crntResnSlot;
-					}
-				}
-
-				matches.emplace_back( cdata, adjType, std::move(newEnv), std::move(have),
-					std::move(newNeed), std::move(newOpenVars), crntResnSlot );
-			} else {
-				delete adjType;
-			}
-		}
-
-		// break if no suitable assertion
-		if ( matches.empty() ) return false;
-
-		// defer if too many suitable assertions
-		if ( matches.size() > 1 ) {
-			resn.deferred.emplace_back( assn.decl, assn.info, std::move(matches) );
-			return true;
-		}
-
-		// otherwise bind current match in ongoing scope
-		AssnCandidate& match = matches.front();
-		addToIndexer( match.have, resn.indexer );
-		resn.newNeed.insert( match.need.begin(), match.need.end() );
-		resn.alt.env = std::move(match.env);
-		resn.alt.openVars = std::move(match.openVars);
-
-		bindAssertion( assn.decl, assn.info, resn.alt, match, resn.inferred );
-		return true;
-	}
-
-	/// Associates inferred parameters with an expression
-	struct InferMatcher {
-		InferCache& inferred;
-
-		InferMatcher( InferCache& inferred ) : inferred( inferred ) {}
-
-		Expression* postmutate( Expression* expr ) {
-			// defer missing inferred parameters until they are hopefully found later
-			std::vector<UniqueId> missingSlots;
-			// place inferred parameters into resolution slots
-			for ( UniqueId slot : expr->resnSlots ) {
-				// fail if no matching parameters found
-				auto it = inferred.find( slot );
-				if ( it == inferred.end() ) {
-					missingSlots.push_back( slot );
-					continue;
-				}
-				InferredParams& inferParams = it->second;
-
-				// place inferred parameters into proper place in expression
-				for ( auto& entry : inferParams ) {
-					// recurse on inferParams of resolved expressions
-					entry.second.expr = postmutate( entry.second.expr );
-					// xxx - look at entry.second.inferParams?
-					auto res = expr->inferParams.emplace( entry.first, entry.second );
-					assert(res.second);
-				}
-			}
-
-			// clear resolution slots and return
-			expr->resnSlots.swap( missingSlots );
-			return expr;
-		}
-	};
-
-	/// Map of alternative return types to recursive assertion satisfaction costs
-	using PruneMap = std::unordered_map<std::string, CostVec>;
-
-	/// Gets the pruning key for an alternative
-	std::string pruneKey( const Alternative & alt ) {
-		Type* resType = alt.expr->result->clone();
-		alt.env.apply( resType );
-		std::string resKey = SymTab::Mangler::mangleType( resType );
-		delete resType;
-		return resKey;
-	}
-
-	/// Replace resnSlots with inferParams and add alternative to output list, if meets pruning
-	/// threshold.
-	void finalizeAssertions( ResnState& resn, PruneMap & pruneThresholds, AltList& out ) {
-		// prune if cheaper alternative for same key has already been generated
-		std::string resKey = pruneKey( resn.alt );
-		auto it = pruneThresholds.find( resKey );
-		if ( it != pruneThresholds.end() ) {
-			if ( it->second < resn.costs ) return;
-		} else {
-			pruneThresholds.emplace_hint( it, resKey, resn.costs );
-		}
-
-		// replace resolution slots with inferred params, add to output
-		PassVisitor<InferMatcher> matcher{ resn.inferred };
-		resn.alt.expr = resn.alt.expr->acceptMutator( matcher );
-		out.emplace_back( resn.alt );
-	}
-
-	/// Limit to depth of recursion of assertion satisfaction
-	static const int recursionLimit = 7;
-	/// Maximum number of simultaneously-deferred assertions to attempt concurrent satisfaction of
-	static const int deferLimit = 10;
-
-	void resolveAssertions( Alternative& alt, const SymTab::Indexer& indexer, AltList& out, std::list<std::string>& errors ) {
-		// finish early if no assertions to resolve
-		if ( alt.need.empty() ) {
-			out.emplace_back( alt );
-			return;
-		}
-
-		// build list of possible resolutions
-		using ResnList = std::vector<ResnState>;
-		SymTab::Indexer root_indexer{ indexer };
-		ResnList resns{ ResnState{ alt, root_indexer } };
-		ResnList new_resns{};
-
-		// Pruning thresholds by result type of the output alternatives.
-		// Alternatives *should* be generated in sorted order, so no need to retroactively prune
-		PruneMap thresholds;
-
-		// resolve assertions in breadth-first-order up to a limited number of levels deep
-		for ( unsigned level = 0; level < recursionLimit; ++level ) {
-			// scan over all mutually-compatible resolutions
-			for ( auto& resn : resns ) {
-				// stop this branch if already found a better option
-				auto it = thresholds.find( pruneKey( resn.alt ) );
-				if ( it != thresholds.end() && it->second < resn.costs ) goto nextResn;
-
-				// make initial pass at matching assertions
-				for ( auto& assn : resn.need ) {
-					// fail early if any assertion is not resolvable
-					if ( ! resolveAssertion( assn, resn ) ) {
-						Indenter tabs{ 3 };
-						std::ostringstream ss;
-						ss << tabs << "Unsatisfiable alternative:\n";
-						resn.alt.print( ss, ++tabs );
-						ss << (tabs-1) << "Could not satisfy assertion:\n";
-						assn.decl->print( ss, tabs );
-
-						errors.emplace_back( ss.str() );
-						goto nextResn;
-					}
-				}
-
-				if ( resn.deferred.empty() ) {
-					// either add successful match or push back next state
-					if ( resn.newNeed.empty() ) {
-						finalizeAssertions( resn, thresholds, out );
-					} else {
-						new_resns.emplace_back( std::move(resn), IterateState );
-					}
-				} else if ( resn.deferred.size() > deferLimit ) {
-					// too many deferred assertions to attempt mutual compatibility
-					Indenter tabs{ 3 };
-					std::ostringstream ss;
-					ss << tabs << "Unsatisfiable alternative:\n";
-					resn.alt.print( ss, ++tabs );
-					ss << (tabs-1) << "Too many non-unique satisfying assignments for "
-						"assertions:\n";
-					for ( const auto& d : resn.deferred ) {
-						d.decl->print( ss, tabs );
-					}
-
-					errors.emplace_back( ss.str() );
-					goto nextResn;
-				} else {
-					// resolve deferred assertions by mutual compatibility
-					std::vector<CandidateEnvMerger::OutType> compatible = filterCombos(
-						resn.deferred,
-						CandidateEnvMerger{ resn.alt.env, resn.alt.openVars, resn.indexer } );
-					// fail early if no mutually-compatible assertion satisfaction
-					if ( compatible.empty() ) {
-						Indenter tabs{ 3 };
-						std::ostringstream ss;
-						ss << tabs << "Unsatisfiable alternative:\n";
-						resn.alt.print( ss, ++tabs );
-						ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n";
-						for ( const auto& d : resn.deferred ) {
-							d.decl->print( ss, tabs );
-						}
-
-						errors.emplace_back( ss.str() );
-						goto nextResn;
-					}
-					// sort by cost for overall pruning
-					CandidateCost coster{ resn.indexer };
-					std::sort( compatible.begin(), compatible.end(), coster );
-
-					for ( auto& compat : compatible ) {
-						ResnState new_resn = resn;
-
-						// add compatible assertions to new resolution state
-						for ( DeferRef r : compat.assns ) {
-							AssnCandidate match = r.match;
-							addToIndexer( match.have, new_resn.indexer );
-							new_resn.newNeed.insert( match.need.begin(), match.need.end() );
-
-							bindAssertion( r.decl, r.info, new_resn.alt, match, new_resn.inferred );
-						}
-
-						// set mutual environment into resolution state
-						new_resn.alt.env = std::move(compat.env);
-						new_resn.alt.openVars = std::move(compat.openVars);
-
-						// mark cost of this path
-						new_resn.costs.back() += compat.cost;
-
-						// either add sucessful match or push back next state
-						if ( new_resn.newNeed.empty() ) {
-							finalizeAssertions( new_resn, thresholds, out );
-						} else {
-							new_resns.emplace_back( std::move(new_resn), IterateState );
-						}
-					}
-				}
-			nextResn:; }
-
-			// finish or reset for next round
-			if ( new_resns.empty() ) return;
-			resns.swap( new_resns );
-			new_resns.clear();
-		}
-
-		// exceeded recursion limit if reaches here
-		if ( out.empty() ) {
-			SemanticError( alt.expr->location, "Too many recursive assertions" );
-		}
-	}
-} // namespace ResolvExpr
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ResolvExpr/ResolveAssertions.h
===================================================================
--- src/ResolvExpr/ResolveAssertions.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,33 +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.
-//
-// ResolveAssertions.h --
-//
-// Author           : Aaron B. Moss
-// Created On       : Fri Oct 05 13:46:00 2018
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Fri Oct 05 13:46:00 2018
-// Update Count     : 1
-//
-
-#pragma once
-
-#include "Alternative.h"  // for Alternative, AltList
-
-namespace SymTab {
-	class Indexer;
-}
-
-namespace ResolvExpr {
-	/// Recursively resolves all assertions provided in an alternative; returns true iff succeeds
-	void resolveAssertions( Alternative& alt, const SymTab::Indexer& indexer, AltList& out, std::list<std::string>& errors );
-} // namespace ResolvExpr
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/ResolvExpr/ResolveTypeof.cc
===================================================================
--- src/ResolvExpr/ResolveTypeof.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/ResolveTypeof.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -24,5 +24,4 @@
 #include "AST/Type.hpp"
 #include "AST/TypeEnvironment.hpp"
-#include "Common/PassVisitor.h"   // for PassVisitor
 #include "Common/utility.h"       // for copy
 #include "InitTweak/InitTweak.h"  // for isConstExpr
@@ -30,97 +29,12 @@
 #include "Resolver.h"  // for resolveInVoidContext
 #include "SymTab/Mangler.h"
-#include "SynTree/Expression.h"  // for Expression
-#include "SynTree/Mutator.h"     // for Mutator
-#include "SynTree/Type.h"        // for TypeofType, Type
-
-namespace SymTab {
-class Indexer;
-}  // namespace SymTab
 
 namespace ResolvExpr {
-namespace {
-#if 0
-		void
-		printAlts( const AltList &list, std::ostream &os, int indent = 0 )
-		{
-			for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
-				i->print( os, indent );
-				os << std::endl;
-			}
-		}
-#endif
-	}
-
-class ResolveTypeof_old : public WithShortCircuiting {
-   public:
-		ResolveTypeof_old( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
-		void premutate( TypeofType *typeofType );
-		Type * postmutate( TypeofType *typeofType );
-
-   private:
-    const SymTab::Indexer &indexer;
-};
-
-	Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
-		PassVisitor<ResolveTypeof_old> mutator( indexer );
-		return type->acceptMutator( mutator );
-	}
-
-	void ResolveTypeof_old::premutate( TypeofType * ) {
-		visit_children = false;
-	}
-
-    Type * ResolveTypeof_old::postmutate( TypeofType *typeofType ) {
-#if 0
-		std::cerr << "resolving typeof: ";
-		typeofType->print( std::cerr );
-		std::cerr << std::endl;
-#endif
-    // pass on null expression
-		if ( ! typeofType->expr ) return typeofType;
-
-    bool isBasetypeof = typeofType->is_basetypeof;
-    auto oldQuals = typeofType->get_qualifiers().val;
-
-    Type* newType;
-		if ( TypeExpr* tyExpr = dynamic_cast<TypeExpr*>(typeofType->expr) ) {
-        // typeof wrapping type
-        newType = tyExpr->type;
-        tyExpr->type = nullptr;
-        delete tyExpr;
-    } else {
-        // typeof wrapping expression
-			Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer );
-			assert( newExpr->result && ! newExpr->result->isVoid() );
-        newType = newExpr->result;
-        newExpr->result = nullptr;
-        delete typeofType;
-        delete newExpr;
-    }
-
-    // clear qualifiers for base, combine with typeoftype quals in any case
-    if ( isBasetypeof ) {
-			// replace basetypeof(<enum>) by int
-			if ( dynamic_cast<EnumInstType*>(newType) ) {
-				Type* newerType =
-					new BasicType{ newType->get_qualifiers(), BasicType::SignedInt,
-					newType->attributes };
-				delete newType;
-				newType = newerType;
-			}
-			newType->get_qualifiers().val
-				= ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals;
-		} else {
-        newType->get_qualifiers().val |= oldQuals;
-    }
-
-    return newType;
-}
 
 namespace {
-struct ResolveTypeof_new : public ast::WithShortCircuiting {
+struct ResolveTypeof : public ast::WithShortCircuiting {
     const ResolveContext & context;
 
-		ResolveTypeof_new( const ResolveContext & context ) :
+		ResolveTypeof( const ResolveContext & context ) :
 			context( context ) {}
 
@@ -164,5 +78,5 @@
 
 const ast::Type * resolveTypeof( const ast::Type * type , const ResolveContext & context ) {
-	ast::Pass< ResolveTypeof_new > mutator( context );
+	ast::Pass< ResolveTypeof > mutator( context );
 	return type->accept( mutator );
 }
Index: src/ResolvExpr/ResolveTypeof.h
===================================================================
--- src/ResolvExpr/ResolveTypeof.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/ResolveTypeof.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,8 +16,4 @@
 #pragma once
 
-class Type;
-namespace SymTab {
-class Indexer;
-}  // namespace SymTab
 namespace ast {
 	class Type;
@@ -28,9 +24,8 @@
 	struct ResolveContext;
 
-	Type *resolveTypeof( Type*, const SymTab::Indexer &indexer );
 	const ast::Type * resolveTypeof( const ast::Type *, const ResolveContext & );
 	const ast::Type * fixArrayType( const ast::Type *, const ResolveContext & );
 	const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & );
-	const ast::ObjectDecl * fixObjectInit( const ast::ObjectDecl * decl , const ResolveContext &);
+	const ast::ObjectDecl * fixObjectInit( const ast::ObjectDecl * decl , const ResolveContext & );
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/Resolver.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -19,6 +19,4 @@
 #include <vector>                        // for vector
 
-#include "Alternative.h"                 // for Alternative, AltList
-#include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
 #include "Candidate.hpp"
 #include "CandidateFinder.hpp"
@@ -40,21 +38,11 @@
 #include "Common/Eval.h"                 // for eval
 #include "Common/Iterate.hpp"            // for group_iterate
-#include "Common/PassVisitor.h"          // for PassVisitor
 #include "Common/SemanticError.h"        // for SemanticError
 #include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
 #include "Common/ToString.hpp"           // for toCString
+#include "Common/UniqueName.h"           // for UniqueName
 #include "InitTweak/GenInit.h"
 #include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
-#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
-#include "SymTab/Autogen.h"              // for SizeType
-#include "SymTab/Indexer.h"              // for Indexer
 #include "SymTab/Mangler.h"              // for Mangler
-#include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
-#include "SynTree/Expression.h"          // for Expression, CastExpr, InitExpr
-#include "SynTree/Initializer.h"         // for ConstructorInit, SingleInit
-#include "SynTree/Statement.h"           // for ForStmt, Statement, BranchStmt
-#include "SynTree/Type.h"                // for Type, BasicType, PointerType
-#include "SynTree/TypeSubstitution.h"    // for TypeSubstitution
-#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
 #include "Tuples/Tuples.h"
 #include "Validate/FindSpecialDecls.h"   // for SizeType
@@ -63,543 +51,4 @@
 
 namespace ResolvExpr {
-	struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd {
-		Resolver_old() {}
-		Resolver_old( const SymTab::Indexer & other ) {
-			indexer = other;
-		}
-
-		void previsit( FunctionDecl * functionDecl );
-		void postvisit( FunctionDecl * functionDecl );
-		void previsit( ObjectDecl * objectDecll );
-		void previsit( EnumDecl * enumDecl );
-		void previsit( StaticAssertDecl * assertDecl );
-
-		void previsit( ArrayType * at );
-		void previsit( PointerType * at );
-
-		void previsit( ExprStmt * exprStmt );
-		void previsit( AsmExpr * asmExpr );
-		void previsit( AsmStmt * asmStmt );
-		void previsit( IfStmt * ifStmt );
-		void previsit( WhileDoStmt * whileDoStmt );
-		void previsit( ForStmt * forStmt );
-		void previsit( SwitchStmt * switchStmt );
-		void previsit( CaseStmt * caseStmt );
-		void previsit( BranchStmt * branchStmt );
-		void previsit( ReturnStmt * returnStmt );
-		void previsit( ThrowStmt * throwStmt );
-		void previsit( CatchStmt * catchStmt );
-		void postvisit( CatchStmt * catchStmt );
-		void previsit( WaitForStmt * stmt );
-
-		void previsit( SingleInit * singleInit );
-		void previsit( ListInit * listInit );
-		void previsit( ConstructorInit * ctorInit );
-	  private:
-		typedef std::list< Initializer * >::iterator InitIterator;
-
-		template< typename PtrType >
-		void handlePtrType( PtrType * type );
-
-		void fallbackInit( ConstructorInit * ctorInit );
-
-		Type * functionReturn = nullptr;
-		CurrentObject currentObject = nullptr;
-		bool inEnumDecl = false;
-	};
-
-	struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {
-		void previsit( FunctionDecl * );
-		void previsit( WithStmt * );
-
-		void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
-	};
-
-	void resolve( std::list< Declaration * > translationUnit ) {
-		PassVisitor<Resolver_old> resolver;
-		acceptAll( translationUnit, resolver );
-	}
-
-	void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {
-		PassVisitor<Resolver_old> resolver( indexer );
-		maybeAccept( decl, resolver );
-	}
-
-	namespace {
-		struct DeleteFinder_old : public WithShortCircuiting	{
-			DeletedExpr * delExpr = nullptr;
-			void previsit( DeletedExpr * expr ) {
-				if ( delExpr ) visit_children = false;
-				else delExpr = expr;
-			}
-
-			void previsit( Expression * ) {
-				if ( delExpr ) visit_children = false;
-			}
-		};
-	}
-
-	DeletedExpr * findDeletedExpr( Expression * expr ) {
-		PassVisitor<DeleteFinder_old> finder;
-		expr->accept( finder );
-		return finder.pass.delExpr;
-	}
-
-	namespace {
-		struct StripCasts_old {
-			Expression * postmutate( CastExpr * castExpr ) {
-				if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
-					// generated cast is to the same type as its argument, so it's unnecessary -- remove it
-					Expression * expr = castExpr->arg;
-					castExpr->arg = nullptr;
-					std::swap( expr->env, castExpr->env );
-					return expr;
-				}
-				return castExpr;
-			}
-
-			static void strip( Expression *& expr ) {
-				PassVisitor<StripCasts_old> stripper;
-				expr = expr->acceptMutator( stripper );
-			}
-		};
-
-		void finishExpr( Expression *& expr, const TypeEnvironment & env, TypeSubstitution * oldenv = nullptr ) {
-			expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
-			env.makeSubstitution( *expr->env );
-			StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression
-		}
-
-		void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
-			if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
-				if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
-					// cast is to the same type as its argument, so it's unnecessary -- remove it
-					expr = castExpr->arg;
-					castExpr->arg = nullptr;
-					std::swap( expr->env, castExpr->env );
-					delete castExpr;
-				}
-			}
-		}
-	} // namespace
-
-	namespace {
-		void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
-			assertf( untyped, "expected a non-null expression." );
-
-			// xxx - this isn't thread-safe, but should work until we parallelize the resolver
-			static unsigned recursion_level = 0;
-
-			++recursion_level;
-			TypeEnvironment env;
-			AlternativeFinder finder( indexer, env );
-			finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
-			--recursion_level;
-
-			#if 0
-			if ( finder.get_alternatives().size() != 1 ) {
-				std::cerr << "untyped expr is ";
-				untyped->print( std::cerr );
-				std::cerr << std::endl << "alternatives are:";
-				for ( const Alternative & alt : finder.get_alternatives() ) {
-					alt.print( std::cerr );
-				} // for
-			} // if
-			#endif
-
-			// produce filtered list of alternatives
-			AltList candidates;
-			for ( Alternative & alt : finder.get_alternatives() ) {
-				if ( pred( alt ) ) {
-					candidates.push_back( std::move( alt ) );
-				}
-			}
-
-			// produce invalid error if no candidates
-			if ( candidates.empty() ) {
-				SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
-			}
-
-			// search for cheapest candidate
-			AltList winners;
-			bool seen_undeleted = false;
-			for ( unsigned i = 0; i < candidates.size(); ++i ) {
-				int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
-
-				if ( c > 0 ) continue; // skip more expensive than winner
-
-				if ( c < 0 ) {
-					// reset on new cheapest
-					seen_undeleted = ! findDeletedExpr( candidates[i].expr );
-					winners.clear();
-				} else /* if ( c == 0 ) */ {
-					if ( findDeletedExpr( candidates[i].expr ) ) {
-						// skip deleted expression if already seen one equivalent-cost not
-						if ( seen_undeleted ) continue;
-					} else if ( ! seen_undeleted ) {
-						// replace list of equivalent-cost deleted expressions with one non-deleted
-						winners.clear();
-						seen_undeleted = true;
-					}
-				}
-
-				winners.emplace_back( std::move( candidates[i] ) );
-			}
-
-			// promote alternative.cvtCost to .cost
-			// xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
-			for ( Alternative& winner : winners ) {
-				winner.cost = winner.cvtCost;
-			}
-
-			// produce ambiguous errors, if applicable
-			if ( winners.size() != 1 ) {
-				std::ostringstream stream;
-				stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
-				untyped->print( stream );
-				stream << " Alternatives are:\n";
-				printAlts( winners, stream, 1 );
-				SemanticError( untyped->location, stream.str() );
-			}
-
-			// single selected choice
-			Alternative& choice = winners.front();
-
-			// fail on only expression deleted
-			if ( ! seen_undeleted ) {
-				SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
-			}
-
-			// xxx - check for ambiguous expressions
-
-			// output selected choice
-			alt = std::move( choice );
-		}
-
-		/// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
-		void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
-			if ( ! untyped ) return;
-			Alternative choice;
-			findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
-			finishExpr( choice.expr, choice.env, untyped->env );
-			delete untyped;
-			untyped = choice.expr;
-			choice.expr = nullptr;
-		}
-
-		bool standardAlternativeFilter( const Alternative & ) {
-			// currently don't need to filter, under normal circumstances.
-			// in the future, this may be useful for removing deleted expressions
-			return true;
-		}
-	} // namespace
-
-	// used in resolveTypeof
-	Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ) {
-		TypeEnvironment env;
-		return resolveInVoidContext( expr, indexer, env );
-	}
-
-	Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment & env ) {
-		// it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
-		// interpretations, an exception has already been thrown.
-		assertf( expr, "expected a non-null expression." );
-
-		CastExpr * untyped = new CastExpr( expr ); // cast to void
-		untyped->location = expr->location;
-
-		// set up and resolve expression cast to void
-		Alternative choice;
-		findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
-		CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
-		assert( castExpr );
-		env = std::move( choice.env );
-
-		// clean up resolved expression
-		Expression * ret = castExpr->arg;
-		castExpr->arg = nullptr;
-
-		// unlink the arg so that it isn't deleted twice at the end of the program
-		untyped->arg = nullptr;
-		return ret;
-	}
-
-	void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
-		resetTyVarRenaming();
-		TypeEnvironment env;
-		Expression * newExpr = resolveInVoidContext( untyped, indexer, env );
-		finishExpr( newExpr, env, untyped->env );
-		delete untyped;
-		untyped = newExpr;
-	}
-
-	void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
-		findKindExpression( untyped, indexer, "", standardAlternativeFilter );
-	}
-
-	void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) {
-		assert( untyped && type );
-		// transfer location to generated cast for error purposes
-		CodeLocation location = untyped->location;
-		untyped = new CastExpr( untyped, type );
-		untyped->location = location;
-		findSingleExpression( untyped, indexer );
-		removeExtraneousCast( untyped, indexer );
-	}
-
-	namespace {
-		bool isIntegralType( const Alternative & alt ) {
-			Type * type = alt.expr->result;
-			if ( dynamic_cast< EnumInstType * >( type ) ) {
-				return true;
-			} else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) {
-				return bt->isInteger();
-			} else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) {
-				return true;
-			} else {
-				return false;
-			} // if
-		}
-
-		void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
-			findKindExpression( untyped, indexer, "condition", isIntegralType );
-		}
-	}
-
-
-	bool isStructOrUnion( const Alternative & alt ) {
-		Type * t = alt.expr->result->stripReferences();
-		return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
-	}
-
-	void resolveWithExprs( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<ResolveWithExprs> resolver;
-		acceptAll( translationUnit, resolver );
-	}
-
-	void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
-		for ( Expression *& expr : withExprs )  {
-			// only struct- and union-typed expressions are viable candidates
-			findKindExpression( expr, indexer, "with statement", isStructOrUnion );
-
-			// if with expression might be impure, create a temporary so that it is evaluated once
-			if ( Tuples::maybeImpure( expr ) ) {
-				static UniqueName tmpNamer( "_with_tmp_" );
-				ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
-				expr = new VariableExpr( tmp );
-				newStmts.push_back( new DeclStmt( tmp ) );
-				if ( InitTweak::isConstructable( tmp->type ) ) {
-					// generate ctor/dtor and resolve them
-					tmp->init = InitTweak::genCtorInit( tmp );
-					tmp->accept( *visitor );
-				}
-			}
-		}
-	}
-
-	void ResolveWithExprs::previsit( WithStmt * withStmt ) {
-		resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
-	}
-
-	void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) {
-		{
-			// resolve with-exprs with parameters in scope and add any newly generated declarations to the
-			// front of the function body.
-			auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } );
-			indexer.addFunctionType( functionDecl->type );
-			std::list< Statement * > newStmts;
-			resolveWithExprs( functionDecl->withExprs, newStmts );
-			if ( functionDecl->statements ) {
-				functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
-			} else {
-				assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
-			}
-		}
-	}
-
-	void Resolver_old::previsit( ObjectDecl * objectDecl ) {
-		// To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
-		// class-variable initContext is changed multiple time because the LHS is analysed twice.
-		// The second analysis changes initContext because of a function type can contain object
-		// declarations in the return and parameter types. So each value of initContext is
-		// retained, so the type on the first analysis is preserved and used for selecting the RHS.
-		GuardValue( currentObject );
-		currentObject = CurrentObject( objectDecl->get_type() );
-		if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
-			// enumerator initializers should not use the enum type to initialize, since
-			// the enum type is still incomplete at this point. Use signed int instead.
-			// TODO: BasicType::SignedInt may not longer be true
-			currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
-		}
-	}
-
-	template< typename PtrType >
-	void Resolver_old::handlePtrType( PtrType * type ) {
-		if ( type->get_dimension() ) {
-			findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
-		}
-	}
-
-	void Resolver_old::previsit( ArrayType * at ) {
-		handlePtrType( at );
-	}
-
-	void Resolver_old::previsit( PointerType * pt ) {
-		handlePtrType( pt );
-	}
-
-	void Resolver_old::previsit( FunctionDecl * functionDecl ) {
-#if 0
-		std::cerr << "resolver visiting functiondecl ";
-		functionDecl->print( std::cerr );
-		std::cerr << std::endl;
-#endif
-		GuardValue( functionReturn );
-		functionReturn = ResolvExpr::extractResultType( functionDecl->type );
-	}
-
-	void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
-		// default value expressions have an environment which shouldn't be there and trips up
-		// later passes.
-		// xxx - it might be necessary to somehow keep the information from this environment, but I
-		// can't currently see how it's useful.
-		for ( Declaration * d : functionDecl->type->parameters ) {
-			if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
-				if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->init ) ) {
-					delete init->value->env;
-					init->value->env = nullptr;
-				}
-			}
-		}
-	}
-
-	void Resolver_old::previsit( EnumDecl * ) {
-		// in case we decide to allow nested enums
-		GuardValue( inEnumDecl );
-		inEnumDecl = true;
-	}
-
-	void Resolver_old::previsit( StaticAssertDecl * assertDecl ) {
-		findIntegralExpression( assertDecl->condition, indexer );
-	}
-
-	void Resolver_old::previsit( ExprStmt * exprStmt ) {
-		visit_children = false;
-		assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
-		findVoidExpression( exprStmt->expr, indexer );
-	}
-
-	void Resolver_old::previsit( AsmExpr * asmExpr ) {
-		visit_children = false;
-		findVoidExpression( asmExpr->operand, indexer );
-	}
-
-	void Resolver_old::previsit( AsmStmt * asmStmt ) {
-		visit_children = false;
-		acceptAll( asmStmt->get_input(), *visitor );
-		acceptAll( asmStmt->get_output(), *visitor );
-	}
-
-	void Resolver_old::previsit( IfStmt * ifStmt ) {
-		findIntegralExpression( ifStmt->condition, indexer );
-	}
-
-	void Resolver_old::previsit( WhileDoStmt * whileDoStmt ) {
-		findIntegralExpression( whileDoStmt->condition, indexer );
-	}
-
-	void Resolver_old::previsit( ForStmt * forStmt ) {
-		if ( forStmt->condition ) {
-			findIntegralExpression( forStmt->condition, indexer );
-		} // if
-
-		if ( forStmt->increment ) {
-			findVoidExpression( forStmt->increment, indexer );
-		} // if
-	}
-
-	void Resolver_old::previsit( SwitchStmt * switchStmt ) {
-		GuardValue( currentObject );
-		findIntegralExpression( switchStmt->condition, indexer );
-
-		currentObject = CurrentObject( switchStmt->condition->result );
-	}
-
-	void Resolver_old::previsit( CaseStmt * caseStmt ) {
-		if ( caseStmt->condition ) {
-			std::list< InitAlternative > initAlts = currentObject.getOptions();
-			assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
-			// must remove cast from case statement because RangeExpr cannot be cast.
-			Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() );
-			findSingleExpression( newExpr, indexer );
-			// case condition cannot have a cast in C, so it must be removed, regardless of whether it performs a conversion.
-			// Ideally we would perform the conversion internally here.
-			if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( newExpr ) ) {
-				newExpr = castExpr->arg;
-				castExpr->arg = nullptr;
-				std::swap( newExpr->env, castExpr->env );
-				delete castExpr;
-			}
-			caseStmt->condition = newExpr;
-		}
-	}
-
-	void Resolver_old::previsit( BranchStmt * branchStmt ) {
-		visit_children = false;
-		// must resolve the argument for a computed goto
-		if ( branchStmt->get_type() == BranchStmt::Goto ) { // check for computed goto statement
-			if ( branchStmt->computedTarget ) {
-				// computed goto argument is void *
-				findSingleExpression( branchStmt->computedTarget, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), indexer );
-			} // if
-		} // if
-	}
-
-	void Resolver_old::previsit( ReturnStmt * returnStmt ) {
-		visit_children = false;
-		if ( returnStmt->expr ) {
-			findSingleExpression( returnStmt->expr, functionReturn->clone(), indexer );
-		} // if
-	}
-
-	void Resolver_old::previsit( ThrowStmt * throwStmt ) {
-		visit_children = false;
-		// TODO: Replace *exception type with &exception type.
-		if ( throwStmt->get_expr() ) {
-			const StructDecl * exception_decl = indexer.lookupStruct( "__cfaehm_base_exception_t" );
-			assert( exception_decl );
-			Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) );
-			findSingleExpression( throwStmt->expr, exceptType, indexer );
-		}
-	}
-
-	void Resolver_old::previsit( CatchStmt * catchStmt ) {
-		// Until we are very sure this invarent (ifs that move between passes have then)
-		// holds, check it. This allows a check for when to decode the mangling.
-		if ( IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body ) ) {
-			assert( ifStmt->then );
-		}
-		// Encode the catchStmt so the condition can see the declaration.
-		if ( catchStmt->cond ) {
-			IfStmt * ifStmt = new IfStmt( catchStmt->cond, nullptr, catchStmt->body );
-			catchStmt->cond = nullptr;
-			catchStmt->body = ifStmt;
-		}
-	}
-
-	void Resolver_old::postvisit( CatchStmt * catchStmt ) {
-		// Decode the catchStmt so everything is stored properly.
-		IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body );
-		if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
-			assert( ifStmt->condition );
-			assert( ifStmt->else_ );
-			catchStmt->cond = ifStmt->condition;
-			catchStmt->body = ifStmt->else_;
-			ifStmt->condition = nullptr;
-			ifStmt->else_ = nullptr;
-			delete ifStmt;
-		}
-	}
-
 	template< typename iterator_t >
 	inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) {
@@ -611,365 +60,7 @@
 	}
 
-	void Resolver_old::previsit( WaitForStmt * stmt ) {
-		visit_children = false;
-
-		// Resolve all clauses first
-		for( auto& clause : stmt->clauses ) {
-
-			TypeEnvironment env;
-			AlternativeFinder funcFinder( indexer, env );
-
-			// Find all alternatives for a function in canonical form
-			funcFinder.findWithAdjustment( clause.target.function );
-
-			if ( funcFinder.get_alternatives().empty() ) {
-				stringstream ss;
-				ss << "Use of undeclared indentifier '";
-				ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
-				ss << "' in call to waitfor";
-				SemanticError( stmt->location, ss.str() );
-			}
-
-			if(clause.target.arguments.empty()) {
-				SemanticError( stmt->location, "Waitfor clause must have at least one mutex parameter");
-			}
-
-			// Find all alternatives for all arguments in canonical form
-			std::vector< AlternativeFinder > argAlternatives;
-			funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) );
-
-			// List all combinations of arguments
-			std::vector< AltList > possibilities;
-			combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
-
-			AltList                func_candidates;
-			std::vector< AltList > args_candidates;
-
-			// For every possible function :
-			// 	try matching the arguments to the parameters
-			// 	not the other way around because we have more arguments than parameters
-			SemanticErrorException errors;
-			for ( Alternative & func : funcFinder.get_alternatives() ) {
-				try {
-					PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
-					if( !pointer ) {
-						SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" );
-					}
-
-					FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
-					if( !function ) {
-						SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
-					}
-
-
-					{
-						auto param     = function->parameters.begin();
-						auto param_end = function->parameters.end();
-
-						if( !advance_to_mutex( param, param_end ) ) {
-							SemanticError(function, "candidate function not viable: no mutex parameters\n");
-						}
-					}
-
-					Alternative newFunc( func );
-					// Strip reference from function
-					referenceToRvalueConversion( newFunc.expr, newFunc.cost );
-
-					// For all the set of arguments we have try to match it with the parameter of the current function alternative
-					for ( auto & argsList : possibilities ) {
-
-						try {
-							// Declare data structures need for resolution
-							OpenVarSet openVars;
-							AssertionSet resultNeed, resultHave;
-							TypeEnvironment resultEnv( func.env );
-							makeUnifiableVars( function, openVars, resultNeed );
-							// add all type variables as open variables now so that those not used in the parameter
-							// list are still considered open.
-							resultEnv.add( function->forall );
-
-							// Load type variables from arguemnts into one shared space
-							simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv );
-
-							// Make sure we don't widen any existing bindings
-							resultEnv.forbidWidening();
-
-							// Find any unbound type variables
-							resultEnv.extractOpenVars( openVars );
-
-							auto param     = function->parameters.begin();
-							auto param_end = function->parameters.end();
-
-							int n_mutex_param = 0;
-
-							// For every arguments of its set, check if it matches one of the parameter
-							// The order is important
-							for( auto & arg : argsList ) {
-
-								// Ignore non-mutex arguments
-								if( !advance_to_mutex( param, param_end ) ) {
-									// We ran out of parameters but still have arguments
-									// this function doesn't match
-									SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" ));
-								}
-
-								n_mutex_param++;
-
-								// Check if the argument matches the parameter type in the current scope
-								if( ! unify( arg.expr->get_result(), (*param)->get_type(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
-									// Type doesn't match
-									stringstream ss;
-									ss << "candidate function not viable: no known convertion from '";
-									(*param)->get_type()->print( ss );
-									ss << "' to '";
-									arg.expr->get_result()->print( ss );
-									ss << "' with env '";
-									resultEnv.print(ss);
-									ss << "'\n";
-									SemanticError( function, ss.str() );
-								}
-
-								param++;
-							}
-
-							// All arguments match !
-
-							// Check if parameters are missing
-							if( advance_to_mutex( param, param_end ) ) {
-								do {
-									n_mutex_param++;
-									param++;
-								} while( advance_to_mutex( param, param_end ) );
-
-								// We ran out of arguments but still have parameters left
-								// this function doesn't match
-								SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" ));
-							}
-
-							// All parameters match !
-
-							// Finish the expressions to tie in the proper environments
-							finishExpr( newFunc.expr, resultEnv );
-							for( Alternative & alt : argsList ) {
-								finishExpr( alt.expr, resultEnv );
-							}
-
-							// This is a match store it and save it for later
-							func_candidates.push_back( newFunc );
-							args_candidates.push_back( argsList );
-
-						}
-						catch( SemanticErrorException & e ) {
-							errors.append( e );
-						}
-					}
-				}
-				catch( SemanticErrorException & e ) {
-					errors.append( e );
-				}
-			}
-
-			// Make sure we got the right number of arguments
-			if( func_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
-			if( args_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
-			if( func_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
-			if( args_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
-			// TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
-
-			// Swap the results from the alternative with the unresolved values.
-			// Alternatives will handle deletion on destruction
-			std::swap( clause.target.function, func_candidates.front().expr );
-			for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) {
-				std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr );
-			}
-
-			// Resolve the conditions as if it were an IfStmt
-			// Resolve the statments normally
-			findSingleExpression( clause.condition, this->indexer );
-			clause.statement->accept( *visitor );
-		}
-
-
-		if( stmt->timeout.statement ) {
-			// Resolve the timeout as an size_t for now
-			// Resolve the conditions as if it were an IfStmt
-			// Resolve the statments normally
-			findSingleExpression( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer );
-			findSingleExpression( stmt->timeout.condition, this->indexer );
-			stmt->timeout.statement->accept( *visitor );
-		}
-
-		if( stmt->orelse.statement ) {
-			// Resolve the conditions as if it were an IfStmt
-			// Resolve the statments normally
-			findSingleExpression( stmt->orelse.condition, this->indexer );
-			stmt->orelse.statement->accept( *visitor );
-		}
-	}
-
-	bool isCharType( Type * t ) {
-		if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) {
-			return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar ||
-				bt->get_kind() == BasicType::UnsignedChar;
-		}
-		return false;
-	}
-
-	void Resolver_old::previsit( SingleInit * singleInit ) {
-		visit_children = false;
-		// resolve initialization using the possibilities as determined by the currentObject cursor
-		Expression * newExpr = new UntypedInitExpr( singleInit->value, currentObject.getOptions() );
-		findSingleExpression( newExpr, indexer );
-		InitExpr * initExpr = strict_dynamic_cast< InitExpr * >( newExpr );
-
-		// move cursor to the object that is actually initialized
-		currentObject.setNext( initExpr->get_designation() );
-
-		// discard InitExpr wrapper and retain relevant pieces
-		newExpr = initExpr->expr;
-		initExpr->expr = nullptr;
-		std::swap( initExpr->env, newExpr->env );
-		// InitExpr may have inferParams in the case where the expression specializes a function
-		// pointer, and newExpr may already have inferParams of its own, so a simple swap is not
-		// sufficient.
-		newExpr->spliceInferParams( initExpr );
-		delete initExpr;
-
-		// get the actual object's type (may not exactly match what comes back from the resolver
-		// due to conversions)
-		Type * initContext = currentObject.getCurrentType();
-
-		removeExtraneousCast( newExpr, indexer );
-
-		// check if actual object's type is char[]
-		if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
-			if ( isCharType( at->get_base() ) ) {
-				// check if the resolved type is char *
-				if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
-					if ( isCharType( pt->get_base() ) ) {
-						if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) {
-							// strip cast if we're initializing a char[] with a char *,
-							// e.g.  char x[] = "hello";
-							newExpr = ce->get_arg();
-							ce->set_arg( nullptr );
-							std::swap( ce->env, newExpr->env );
-							delete ce;
-						}
-					}
-				}
-			}
-		}
-
-		// set initializer expr to resolved express
-		singleInit->value = newExpr;
-
-		// move cursor to next object in preparation for next initializer
-		currentObject.increment();
-	}
-
-	void Resolver_old::previsit( ListInit * listInit ) {
-		visit_children = false;
-		// move cursor into brace-enclosed initializer-list
-		currentObject.enterListInit();
-		// xxx - fix this so that the list isn't copied, iterator should be used to change current
-		// element
-		std::list<Designation *> newDesignations;
-		for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
-			// iterate designations and initializers in pairs, moving the cursor to the current
-			// designated object and resolving the initializer against that object.
-			Designation * des = std::get<0>(p);
-			Initializer * init = std::get<1>(p);
-			newDesignations.push_back( currentObject.findNext( des ) );
-			init->accept( *visitor );
-		}
-		// set the set of 'resolved' designations and leave the brace-enclosed initializer-list
-		listInit->get_designations() = newDesignations; // xxx - memory management
-		currentObject.exitListInit();
-
-		// xxx - this part has not be folded into CurrentObject yet
-		// } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) {
-		// 	Type * base = tt->get_baseType()->get_base();
-		// 	if ( base ) {
-		// 		// know the implementation type, so try using that as the initContext
-		// 		ObjectDecl tmpObj( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, base->clone(), nullptr );
-		// 		currentObject = &tmpObj;
-		// 		visit( listInit );
-		// 	} else {
-		// 		// missing implementation type -- might be an unknown type variable, so try proceeding with the current init context
-		// 		Parent::visit( listInit );
-		// 	}
-		// } else {
-	}
-
-	// ConstructorInit - fall back on C-style initializer
-	void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) {
-		// could not find valid constructor, or found an intrinsic constructor
-		// fall back on C-style initializer
-		delete ctorInit->get_ctor();
-		ctorInit->set_ctor( nullptr );
-		delete ctorInit->get_dtor();
-		ctorInit->set_dtor( nullptr );
-		maybeAccept( ctorInit->get_init(), *visitor );
-	}
-
-	// needs to be callable from outside the resolver, so this is a standalone function
-	void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
-		assert( ctorInit );
-		PassVisitor<Resolver_old> resolver( indexer );
-		ctorInit->accept( resolver );
-	}
-
-	void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
-		assert( stmtExpr );
-		PassVisitor<Resolver_old> resolver( indexer );
-		stmtExpr->accept( resolver );
-		stmtExpr->computeResult();
-		// xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead?
-	}
-
-	void Resolver_old::previsit( ConstructorInit * ctorInit ) {
-		visit_children = false;
-		// xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
-		maybeAccept( ctorInit->ctor, *visitor );
-		maybeAccept( ctorInit->dtor, *visitor );
-
-		// found a constructor - can get rid of C-style initializer
-		delete ctorInit->init;
-		ctorInit->init = nullptr;
-
-		// intrinsic single parameter constructors and destructors do nothing. Since this was
-		// implicitly generated, there's no way for it to have side effects, so get rid of it
-		// to clean up generated code.
-		if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
-			delete ctorInit->ctor;
-			ctorInit->ctor = nullptr;
-		}
-
-		if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
-			delete ctorInit->dtor;
-			ctorInit->dtor = nullptr;
-		}
-
-		// xxx - todo -- what about arrays?
-		// if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
-		// 	// can reduce the constructor down to a SingleInit using the
-		// 	// second argument from the ctor call, since
-		// 	delete ctorInit->get_ctor();
-		// 	ctorInit->set_ctor( nullptr );
-
-		// 	Expression * arg =
-		// 	ctorInit->set_init( new SingleInit( arg ) );
-		// }
-	}
-
-	///////////////////////////////////////////////////////////////////////////
-	//
-	// *** NEW RESOLVER ***
-	//
-	///////////////////////////////////////////////////////////////////////////
-
 	namespace {
 		/// Finds deleted expressions in an expression tree
-		struct DeleteFinder_new final : public ast::WithShortCircuiting, public ast::WithVisitorRef<DeleteFinder_new> {
+		struct DeleteFinder final : public ast::WithShortCircuiting, public ast::WithVisitorRef<DeleteFinder> {
 			const ast::DeletedExpr * result = nullptr;
 
@@ -989,9 +80,9 @@
 		};
 
-		struct ResolveDesignators_new final : public ast::WithShortCircuiting {
+		struct ResolveDesignators final : public ast::WithShortCircuiting {
 			ResolveContext& context;
 			bool result = false;
 
-			ResolveDesignators_new( ResolveContext& _context ): context{_context} {};
+			ResolveDesignators( ResolveContext& _context ): context{_context} {};
 
 			void previsit( const ast::Node * ) {
@@ -1022,5 +113,5 @@
 	/// Check if this expression is or includes a deleted expression
 	const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
-		return ast::Pass<DeleteFinder_new>::read( expr );
+		return ast::Pass<DeleteFinder>::read( expr );
 	}
 
@@ -1112,5 +203,5 @@
 
 		/// Strips extraneous casts out of an expression
-		struct StripCasts_new final {
+		struct StripCasts final {
 			const ast::Expr * postvisit( const ast::CastExpr * castExpr ) {
 				if (
@@ -1126,5 +217,5 @@
 
 			static void strip( ast::ptr< ast::Expr > & expr ) {
-				ast::Pass< StripCasts_new > stripper;
+				ast::Pass< StripCasts > stripper;
 				expr = expr->accept( stripper );
 			}
@@ -1160,5 +251,5 @@
 			expr.get_and_mutate()->env = std::move( newenv );
 			// remove unncecessary casts
-			StripCasts_new::strip( expr );
+			StripCasts::strip( expr );
 		}
 
@@ -1277,7 +368,7 @@
 	}
 
-	class Resolver_new final
+	class Resolver final
 	: public ast::WithSymbolTable, public ast::WithGuards,
-	  public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting,
+	  public ast::WithVisitorRef<Resolver>, public ast::WithShortCircuiting,
 	  public ast::WithStmtsToAdd<> {
 
@@ -1285,5 +376,5 @@
 		ast::CurrentObject currentObject;
 		// for work previously in GenInit
-		static InitTweak::ManagedTypes_new managedTypes;
+		static InitTweak::ManagedTypes managedTypes;
 		ResolveContext context;
 
@@ -1292,8 +383,8 @@
 	public:
 		static size_t traceId;
-		Resolver_new( const ast::TranslationGlobal & global ) :
+		Resolver( const ast::TranslationGlobal & global ) :
 			ast::WithSymbolTable(ast::SymbolTable::ErrorDetection::ValidateOnAdd),
 			context{ symtab, global } {}
-		Resolver_new( const ResolveContext & context ) :
+		Resolver( const ResolveContext & context ) :
 			ast::WithSymbolTable{ context.symtab },
 			context{ symtab, context.global } {}
@@ -1336,10 +427,10 @@
 		bool on_error(ast::ptr<ast::Decl> & decl);
 	};
-	// size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver");
-
-	InitTweak::ManagedTypes_new Resolver_new::managedTypes;
+	// size_t Resolver::traceId = Stats::Heap::new_stacktrace_id("Resolver");
+
+	InitTweak::ManagedTypes Resolver::managedTypes;
 
 	void resolve( ast::TranslationUnit& translationUnit ) {
-		ast::Pass< Resolver_new >::run( translationUnit, translationUnit.global );
+		ast::Pass< Resolver >::run( translationUnit, translationUnit.global );
 	}
 
@@ -1348,5 +439,5 @@
 	) {
 		assert( ctorInit );
-		ast::Pass< Resolver_new > resolver( context );
+		ast::Pass< Resolver > resolver( context );
 		return ctorInit->accept( resolver );
 	}
@@ -1356,5 +447,5 @@
 	) {
 		assert( stmtExpr );
-		ast::Pass< Resolver_new > resolver( context );
+		ast::Pass< Resolver > resolver( context );
 		auto ret = mutate(stmtExpr->accept(resolver));
 		strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult();
@@ -1398,5 +489,5 @@
 	}
 
-	const ast::FunctionDecl * Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
+	const ast::FunctionDecl * Resolver::previsit( const ast::FunctionDecl * functionDecl ) {
 		GuardValue( functionReturn );
 
@@ -1472,5 +563,5 @@
 	}
 
-	const ast::FunctionDecl * Resolver_new::postvisit( const ast::FunctionDecl * functionDecl ) {
+	const ast::FunctionDecl * Resolver::postvisit( const ast::FunctionDecl * functionDecl ) {
 		// default value expressions have an environment which shouldn't be there and trips up
 		// later passes.
@@ -1500,5 +591,5 @@
 	}
 
-	const ast::ObjectDecl * Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
+	const ast::ObjectDecl * Resolver::previsit( const ast::ObjectDecl * objectDecl ) {
 		// To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
 		// class-variable `initContext` is changed multiple times because the LHS is analyzed
@@ -1539,5 +630,5 @@
 					// constructed objects cannot be designated
 					if ( InitTweak::isDesignated( mutDecl->init ) ) {
-						ast::Pass<ResolveDesignators_new> res( context );
+						ast::Pass<ResolveDesignators> res( context );
 						maybe_accept( mutDecl->init.get(), res );
 						if ( !res.core.result ) {
@@ -1559,5 +650,5 @@
 	}
 
-	void Resolver_new::previsit( const ast::AggregateDecl * _aggDecl ) {
+	void Resolver::previsit( const ast::AggregateDecl * _aggDecl ) {
 		auto aggDecl = mutate(_aggDecl);
 		assertf(aggDecl == _aggDecl, "type declarations must be unique");
@@ -1571,10 +662,10 @@
 	}
 
-	void Resolver_new::previsit( const ast::StructDecl * structDecl ) {
+	void Resolver::previsit( const ast::StructDecl * structDecl ) {
 		previsit(static_cast<const ast::AggregateDecl *>(structDecl));
 		managedTypes.handleStruct(structDecl);
 	}
 
-	void Resolver_new::previsit( const ast::EnumDecl * ) {
+	void Resolver::previsit( const ast::EnumDecl * ) {
 		// in case we decide to allow nested enums
 		GuardValue( inEnumDecl );
@@ -1583,5 +674,5 @@
 	}
 
-	const ast::StaticAssertDecl * Resolver_new::previsit(
+	const ast::StaticAssertDecl * Resolver::previsit(
 		const ast::StaticAssertDecl * assertDecl
 	) {
@@ -1603,13 +694,13 @@
 	}
 
-	const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) {
+	const ast::ArrayType * Resolver::previsit( const ast::ArrayType * at ) {
 		return handlePtrType( at, context );
 	}
 
-	const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) {
+	const ast::PointerType * Resolver::previsit( const ast::PointerType * pt ) {
 		return handlePtrType( pt, context );
 	}
 
-	const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
+	const ast::ExprStmt * Resolver::previsit( const ast::ExprStmt * exprStmt ) {
 		visit_children = false;
 		assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );
@@ -1619,5 +710,5 @@
 	}
 
-	const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
+	const ast::AsmExpr * Resolver::previsit( const ast::AsmExpr * asmExpr ) {
 		visit_children = false;
 
@@ -1628,5 +719,5 @@
 	}
 
-	const ast::AsmStmt * Resolver_new::previsit( const ast::AsmStmt * asmStmt ) {
+	const ast::AsmStmt * Resolver::previsit( const ast::AsmStmt * asmStmt ) {
 		visitor->maybe_accept( asmStmt, &ast::AsmStmt::input );
 		visitor->maybe_accept( asmStmt, &ast::AsmStmt::output );
@@ -1635,15 +726,15 @@
 	}
 
-	const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
+	const ast::IfStmt * Resolver::previsit( const ast::IfStmt * ifStmt ) {
 		return ast::mutate_field(
 			ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, context ) );
 	}
 
-	const ast::WhileDoStmt * Resolver_new::previsit( const ast::WhileDoStmt * whileDoStmt ) {
+	const ast::WhileDoStmt * Resolver::previsit( const ast::WhileDoStmt * whileDoStmt ) {
 		return ast::mutate_field(
 			whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, context ) );
 	}
 
-	const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) {
+	const ast::ForStmt * Resolver::previsit( const ast::ForStmt * forStmt ) {
 		if ( forStmt->cond ) {
 			forStmt = ast::mutate_field(
@@ -1659,5 +750,5 @@
 	}
 
-	const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
+	const ast::SwitchStmt * Resolver::previsit( const ast::SwitchStmt * switchStmt ) {
 		GuardValue( currentObject );
 		switchStmt = ast::mutate_field(
@@ -1668,5 +759,5 @@
 	}
 
-	const ast::CaseClause * Resolver_new::previsit( const ast::CaseClause * caseStmt ) {
+	const ast::CaseClause * Resolver::previsit( const ast::CaseClause * caseStmt ) {
 		if ( caseStmt->cond ) {
 			std::deque< ast::InitAlternative > initAlts = currentObject.getOptions();
@@ -1689,5 +780,5 @@
 	}
 
-	const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
+	const ast::BranchStmt * Resolver::previsit( const ast::BranchStmt * branchStmt ) {
 		visit_children = false;
 		// must resolve the argument of a computed goto
@@ -1702,5 +793,5 @@
 	}
 
-	const ast::ReturnStmt * Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) {
+	const ast::ReturnStmt * Resolver::previsit( const ast::ReturnStmt * returnStmt ) {
 		visit_children = false;
 		if ( returnStmt->expr ) {
@@ -1712,5 +803,5 @@
 	}
 
-	const ast::ThrowStmt * Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) {
+	const ast::ThrowStmt * Resolver::previsit( const ast::ThrowStmt * throwStmt ) {
 		visit_children = false;
 		if ( throwStmt->expr ) {
@@ -1727,5 +818,5 @@
 	}
 
-	const ast::CatchClause * Resolver_new::previsit( const ast::CatchClause * catchClause ) {
+	const ast::CatchClause * Resolver::previsit( const ast::CatchClause * catchClause ) {
 		// Until we are very sure this invarent (ifs that move between passes have then)
 		// holds, check it. This allows a check for when to decode the mangling.
@@ -1743,5 +834,5 @@
 	}
 
-	const ast::CatchClause * Resolver_new::postvisit( const ast::CatchClause * catchClause ) {
+	const ast::CatchClause * Resolver::postvisit( const ast::CatchClause * catchClause ) {
 		// Decode the catchStmt so everything is stored properly.
 		const ast::IfStmt * ifStmt = catchClause->body.as<ast::IfStmt>();
@@ -1758,5 +849,5 @@
 	}
 
-	const ast::WaitForStmt * Resolver_new::previsit( const ast::WaitForStmt * stmt ) {
+	const ast::WaitForStmt * Resolver::previsit( const ast::WaitForStmt * stmt ) {
 		visit_children = false;
 
@@ -2023,5 +1114,5 @@
 	}
 
-	const ast::WithStmt * Resolver_new::previsit( const ast::WithStmt * withStmt ) {
+	const ast::WithStmt * Resolver::previsit( const ast::WithStmt * withStmt ) {
 		auto mutStmt = mutate(withStmt);
 		resolveWithExprs(mutStmt->exprs, stmtsToAddBefore);
@@ -2029,5 +1120,5 @@
 	}
 
-	void Resolver_new::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) {
+	void Resolver::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) {
 		for (auto & expr : exprs) {
 			// only struct- and union-typed expressions are viable candidates
@@ -2055,5 +1146,5 @@
 
 
-	const ast::SingleInit * Resolver_new::previsit( const ast::SingleInit * singleInit ) {
+	const ast::SingleInit * Resolver::previsit( const ast::SingleInit * singleInit ) {
 		visit_children = false;
 		// resolve initialization using the possibilities as determined by the `currentObject`
@@ -2104,5 +1195,5 @@
 	}
 
-	const ast::ListInit * Resolver_new::previsit( const ast::ListInit * listInit ) {
+	const ast::ListInit * Resolver::previsit( const ast::ListInit * listInit ) {
 		// move cursor into brace-enclosed initializer-list
 		currentObject.enterListInit( listInit->location );
@@ -2127,5 +1218,5 @@
 	}
 
-	const ast::ConstructorInit * Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) {
+	const ast::ConstructorInit * Resolver::previsit( const ast::ConstructorInit * ctorInit ) {
 		visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor );
 		visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor );
@@ -2149,5 +1240,5 @@
 
 	// suppress error on autogen functions and mark invalid autogen as deleted.
-	bool Resolver_new::on_error(ast::ptr<ast::Decl> & decl) {
+	bool Resolver::on_error(ast::ptr<ast::Decl> & decl) {
 		if (auto functionDecl = decl.as<ast::FunctionDecl>()) {
 			// xxx - can intrinsic gen ever fail?
Index: src/ResolvExpr/Resolver.h
===================================================================
--- src/ResolvExpr/Resolver.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/Resolver.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,17 +16,5 @@
 #pragma once
 
-#include <list>          // for list
-
 #include "AST/Node.hpp"  // for ptr
-
-class ConstructorInit;
-class Declaration;
-class Expression;
-class DeletedExpr;
-class StmtExpr;
-class Type;
-namespace SymTab {
-	class Indexer;
-} // namespace SymTab
 
 namespace ast {
@@ -45,17 +33,4 @@
 
 namespace ResolvExpr {
-	/// Checks types and binds syntactic constructs to typed representations
-	void resolve( std::list< Declaration * > translationUnit );
-	void resolveDecl( Declaration *, const SymTab::Indexer & indexer );
-	Expression *resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer );
-	void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer );
-	void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer );
-	void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer );
-	void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
-	void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
-	/// Searches expr and returns the first DeletedExpr found, otherwise nullptr
-	DeletedExpr * findDeletedExpr( Expression * expr );
-	/// Resolves with-stmts and with-clauses on functions
-	void resolveWithExprs( std::list< Declaration * > & translationUnit );
 
 	/// Helper Type: Passes around information between various sub-calls.
Index: src/ResolvExpr/SatisfyAssertions.cpp
===================================================================
--- src/ResolvExpr/SatisfyAssertions.cpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/SatisfyAssertions.cpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -46,6 +46,4 @@
 #include "SymTab/Mangler.h"
 
-
-
 namespace ResolvExpr {
 
Index: src/ResolvExpr/SpecCost.cc
===================================================================
--- src/ResolvExpr/SpecCost.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/SpecCost.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,106 +16,21 @@
 #include <cassert>
 #include <limits>
-#include <list>
 #include <type_traits>
 
 #include "AST/Pass.hpp"
 #include "AST/Type.hpp"
-#include "Common/PassVisitor.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/Expression.h"
-#include "SynTree/Type.h"
 
 namespace ResolvExpr {
 
-	/// Counts specializations in a type
-	class CountSpecs : public WithShortCircuiting, public WithVisitorRef<CountSpecs> {
-		int count = -1;  ///< specialization count (-1 for none)
+namespace {
 
-	public:
-		int get_count() const { return count >= 0 ? count : 0; }
+const ast::Type * expr_result( const ast::ptr< ast::Expr > & expr ) {
+	return expr->result.get();
+}
 
-		// mark specialization of base type
-		void postvisit(PointerType*) { if ( count >= 0 ) ++count; }
+const ast::Type * type_deref( const ast::ptr< ast::Type > & type ) {
+	return type.get();
+}
 
-		// mark specialization of base type
-		void postvisit(ArrayType*) { if ( count >= 0 ) ++count; }
-
-		// mark specialization of base type
-		void postvisit(ReferenceType*) { if ( count >= 0 ) ++count; }
-
-		void postvisit(StructInstType*) { if ( count >= 0 ) ++count; }
-		void postvisit(UnionInstType*) { if ( count >= 0 ) ++count; }
-
-	private:
-		// takes minimum non-negative count over parameter/return list
-		void takeminover( int& mincount, std::list<DeclarationWithType*>& dwts ) {
-			for ( DeclarationWithType* dwt : dwts ) {
-				count = -1;
-				maybeAccept( dwt->get_type(), *visitor );
-				if ( count != -1 && count < mincount ) mincount = count;
-			}
-		}
-
-	public:
-		// take minimal specialization value over ->returnVals and ->parameters
-		void previsit(FunctionType* fty) {
-			int mincount = std::numeric_limits<int>::max();
-			takeminover( mincount, fty->parameters );
-			takeminover( mincount, fty->returnVals );
-			// add another level to mincount if set
-			count = mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
-			// already visited children
-			visit_children = false;
-		}
-
-	private:
-		// returns minimum non-negative count + 1 over type parameters (-1 if none such)
-		int minover( std::list<Expression*>& parms ) {
-			int mincount = std::numeric_limits<int>::max();
-			for ( Expression* parm : parms ) {
-				count = -1;
-				maybeAccept( parm->result, *visitor );
-				if ( count != -1 && count < mincount ) mincount = count;
-			}
-			return mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
-		}
-
-	public:
-		// look for polymorphic parameters
-		void previsit(StructInstType* sty) {
-			count = minover( sty->parameters );
-		}
-
-		// look for polymorphic parameters
-		void previsit(UnionInstType* uty) {
-			count = minover( uty->parameters );
-		}
-
-		// note polymorphic type (which may be specialized)
-		// xxx - maybe account for open/closed type variables
-		void postvisit(TypeInstType*) { count = 0; }
-
-		// take minimal specialization over elements
-		// xxx - maybe don't increment, tuple flattening doesn't necessarily specialize
-		void previsit(TupleType* tty) {
-			int mincount = std::numeric_limits<int>::max();
-			for ( Type* ty : tty->types ) {
-				count = -1;
-				maybeAccept( ty, *visitor );
-				if ( count != -1 && count < mincount ) mincount = count;
-			}
-			count = mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
-			visit_children = false;
-		}
-	};
-
-	/// Returns the (negated) specialization cost for a given type
-	int specCost( Type* ty ) {
-		PassVisitor<CountSpecs> counter;
-		maybeAccept( ty, *counter.pass.visitor );
-		return counter.pass.get_count();
-	}
-
-namespace {
 	/// The specialization counter inner class.
 	class SpecCounter : public ast::WithShortCircuiting, public ast::WithVisitorRef<SpecCounter> {
@@ -131,12 +46,4 @@
 			typename std::add_pointer<ast::Type const *(typename T::value_type const &)>::type;
 
-		#warning Should use a standard maybe_accept
-		void maybe_accept( ast::Type const * type ) {
-			if ( type ) {
-				auto node = type->accept( *visitor );
-				assert( node == nullptr || node == type );
-			}
-		}
-
 		// Update the minimum to the new lowest non-none value.
 		template<typename T>
@@ -144,5 +51,10 @@
 			for ( const auto & node : list ) {
 				count = -1;
-				maybe_accept( mapper( node ) );
+
+				if ( ast::Type const * type = mapper( node ) ) {
+					ast::Type const * newType = type->accept( *visitor );
+					assert( newType == nullptr || newType == type );
+				}
+
 				if ( count != -1 && count < minimum ) minimum = count;
 			}
@@ -157,17 +69,6 @@
 		}
 
-		// The three mappers:
-		static const ast::Type * decl_type( const ast::ptr< ast::DeclWithType > & decl ) {
-			return decl->get_type();
-		}
-		static const ast::Type * expr_result( const ast::ptr< ast::Expr > & expr ) {
-			return expr->result;
-		}
-		static const ast::Type * type_deref( const ast::ptr< ast::Type > & type ) {
-			return type.get();
-		}
-
 	public:
-		int get_count() const { return 0 <= count ? count : 0; }
+		int result() const { return 0 <= count ? count : 0; }
 
 		// Mark specialization of base type.
@@ -215,10 +116,5 @@
 
 int specCost( const ast::Type * type ) {
-	if ( nullptr == type ) {
-		return 0;
-	}
-	ast::Pass<SpecCounter> counter;
-	type->accept( counter );
-	return counter.core.get_count();
+	return ( nullptr == type ) ? 0 : ast::Pass<SpecCounter>::read( type );
 }
 
Index: c/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(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.
-//
-// TypeEnvironment.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 12:19:47 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri Jun 18 14:27:00 2019
-// Update Count     : 5
-//
-
-#include <cassert>                     // for assert
-#include <algorithm>                   // for copy, set_intersection
-#include <iterator>                    // for ostream_iterator, insert_iterator
-#include <memory>                      // for unique_ptr
-#include <utility>                     // for pair, move
-
-#include "CompilationState.h"          // for deterministic_output
-#include "Common/utility.h"            // for maybeClone
-#include "SynTree/Type.h"              // for Type, FunctionType, Type::Fora...
-#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
-#include "Tuples/Tuples.h"             // for isTtype
-#include "TypeEnvironment.h"
-#include "typeops.h"                   // for occurs
-#include "Unify.h"                     // for unifyInexact
-
-namespace ResolvExpr {
-	void printAssertionSet( const AssertionSet &assertions, std::ostream &os, int indent ) {
-		for ( AssertionSet::const_iterator i = assertions.begin(); i != assertions.end(); ++i ) {
-			i->first->print( os, indent );
-			if ( i->second.isUsed ) {
-				os << "(used)";
-			} else {
-				os << "(not used)";
-			} // if
-		} // for
-	}
-
-	void printOpenVarSet( const OpenVarSet &openVars, std::ostream &os, int indent ) {
-		os << std::string( indent, ' ' );
-		for ( OpenVarSet::const_iterator i = openVars.begin(); i != openVars.end(); ++i ) {
-			os << i->first << "(" << i->second << ") ";
-		} // for
-	}
-
-	void EqvClass::initialize( const EqvClass &src, EqvClass &dest ) {
-		initialize( src, dest, src.type );
-	}
-
-	void EqvClass::initialize( const EqvClass &src, EqvClass &dest, const Type *ty ) {
-		dest.vars = src.vars;
-		dest.type = maybeClone( ty );
-		dest.allowWidening = src.allowWidening;
-		dest.data = src.data;
-	}
-
-	EqvClass::EqvClass() : type( nullptr ), allowWidening( true ) {
-	}
-
-	EqvClass::EqvClass( const EqvClass &other ) {
-		initialize( other, *this );
-	}
-
-	EqvClass::EqvClass( const EqvClass &other, const Type *ty ) {
-		initialize( other, *this, ty );
-	}
-
-	EqvClass::EqvClass( EqvClass &&other )
-	: vars{std::move(other.vars)}, type{other.type},
-	  allowWidening{std::move(other.allowWidening)}, data{std::move(other.data)} {
-		  other.type = nullptr;
-	}
-
-	EqvClass &EqvClass::operator=( const EqvClass &other ) {
-		if ( this == &other ) return *this;
-		delete type;
-		initialize( other, *this );
-		return *this;
-	}
-
-	EqvClass &EqvClass::operator=( EqvClass &&other ) {
-		if ( this == &other ) return *this;
-		delete type;
-
-		vars = std::move(other.vars);
-		type = other.type;
-		other.type = nullptr;
-		allowWidening = std::move(other.allowWidening);
-		data = std::move(other.data);
-
-		return *this;
-	}
-
-	EqvClass::~EqvClass() {
-		delete type;
-	}
-
-	void EqvClass::set_type( Type* ty ) {
-		if ( ty == type ) return;
-		delete type;
-		type = ty;
-	}
-
-	void EqvClass::print( std::ostream &os, Indenter indent ) const {
-		os << "(";
-		bool first = true;
-		for(const auto & var : vars) {
-			if(first) first = false;
-			else os << " ";
-			if( deterministic_output && isUnboundType(var) ) os << "[unbound]";
-			else os << var;
-		}
-		os << ")";
-		if ( type ) {
-			os << " -> ";
-			type->print( os, indent+1 );
-		} // if
-		if ( ! allowWidening ) {
-			os << " (no widening)";
-		} // if
-		os << std::endl;
-	}
-
-	const EqvClass* TypeEnvironment::lookup( const std::string &var ) const {
-		for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) {
-			if ( i->vars.find( var ) != i->vars.end() ) return &*i;
-		} // for
-		return nullptr;
-	}
-
-	/// Removes any class from env that intersects eqvClass
-	void filterOverlappingClasses( std::list<EqvClass> &env, const EqvClass &eqvClass ) {
-		for ( auto i = env.begin(); i != env.end(); ) {
-			auto next = i;
-			++next;
-			std::set<std::string> intersection;
-			std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(),
-				std::inserter( intersection, intersection.begin() ) );
-			if ( ! intersection.empty() ) { env.erase( i ); }
-			i = next;
-		}
-	}
-
-	void TypeEnvironment::add( EqvClass &&eqvClass ) {
-		filterOverlappingClasses( env, eqvClass );
-		env.push_back( std::move(eqvClass) );
-	}
-
-	void TypeEnvironment::add( const Type::ForallList &tyDecls ) {
-		for ( Type::ForallList::const_iterator i = tyDecls.begin(); i != tyDecls.end(); ++i ) {
-			EqvClass newClass;
-			newClass.vars.insert( (*i)->get_name() );
-			newClass.data = TypeDecl::Data{ (*i) };
-			env.push_back( std::move(newClass) );
-		} // for
-	}
-
-	void TypeEnvironment::add( const TypeSubstitution & sub ) {
-		EqvClass newClass;
-		for ( auto p : sub ) {
-			newClass.vars.insert( p.first );
-			newClass.type = p.second->clone();
-			newClass.allowWidening = false;
-			// Minimal assumptions. Not technically correct, but might be good enough, and
-			// is the best we can do at the moment since information is lost in the
-			// transition to TypeSubstitution
-			newClass.data = TypeDecl::Data{ TypeDecl::Dtype, false };
-			add( std::move(newClass) );
-		}
-	}
-
-	void TypeEnvironment::makeSubstitution( TypeSubstitution &sub ) const {
-		for ( ClassList::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
-			for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
-				if ( theClass->type ) {
-					sub.add( *theVar, theClass->type );
-				} else if ( theVar != theClass->vars.begin() ) {
-					TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype );
-					sub.add( *theVar, newTypeInst );
-					delete newTypeInst;
-				} // if
-			} // for
-		} // for
-		sub.normalize();
-	}
-
-	void TypeEnvironment::print( std::ostream &os, Indenter indent ) const {
-		for ( const EqvClass & theClass : env ) {
-			theClass.print( os, indent );
-		} // for
-	}
-
-	TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string &var ) {
-		for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) {
-			if ( i->vars.count( var ) ) return i;
-		} // for
-		return env.end();
-	}
-
-	void TypeEnvironment::simpleCombine( const TypeEnvironment &second ) {
-		env.insert( env.end(), second.env.begin(), second.env.end() );
-	}
-
-	// xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto)
-	bool TypeEnvironment::mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
-		if ( from.type ) {
-			if ( to.type ) {
-				// attempt to unify bound types
-				std::unique_ptr<Type> toType{ to.type->clone() }, fromType{ from.type->clone() };
-				WidenMode widen{ to.allowWidening, from.allowWidening };
-				Type* common = nullptr;
-				AssertionSet need, have;
-				if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widen, indexer, common ) ) {
-					// unifies, set common type if necessary
-					if ( common ) {
-						common->get_qualifiers() = Type::Qualifiers{};
-						to.set_type( common );
-					}
-				} else return false; // cannot unify
-			} else {
-				to.type = from.type->clone();
-			}
-		}
-
-		// unify widening if matches
-		to.allowWidening &= from.allowWidening;
-		return true;
-	}
-
-	// xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto)
-	bool TypeEnvironment::mergeClasses( TypeEnvironment::ClassList::iterator to, TypeEnvironment::ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
-		EqvClass& r = *to;
-		EqvClass& s = *from;
-
-		// ensure bounds match
-		if ( ! mergeBound( r, s, openVars, indexer ) ) return false;
-
-		// check safely bindable
-		if ( r.type && occursIn( r.type, s.vars.begin(), s.vars.end(), *this ) ) return false;
-
-		// merge classes in
-		r.vars.insert( s.vars.begin(), s.vars.end() );
-		r.allowWidening &= s.allowWidening;
-		env.erase( from );
-
-		return true;
-	}
-
-	bool TypeEnvironment::combine( const TypeEnvironment& o, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
-		// short-circuit easy cases
-		if ( o.isEmpty() ) return true;
-		if ( isEmpty() ) {
-			simpleCombine( o );
-			return true;
-		}
-
-		// merge classes
-		for ( auto ct = o.env.begin(); ct != o.env.end(); ++ct ) {
-			const EqvClass& c = *ct;
-
-			// typeclass in local environment bound to c
-			auto rt = env.end();
-
-			// look for first existing bound variable
-			auto vt = c.vars.begin();
-			for ( ; vt != c.vars.end(); ++vt ) {
-				rt = internal_lookup( *vt );
-				if ( rt != env.end() ) break;
-			}
-
-			if ( rt != env.end() ) {  // c needs to be merged into *rt
-				EqvClass& r = *rt;
-				// merge bindings
-				if ( ! mergeBound( r, c, openVars, indexer ) ) return false;
-				// merge previous unbound variables into this class, checking occurs if needed
-				if ( r.type ) for ( auto ut = c.vars.begin(); ut != vt; ++ut ) {
-					if ( occurs( r.type, *ut, *this ) ) return false;
-					r.vars.insert( *ut );
-				} else { r.vars.insert( c.vars.begin(), vt ); }
-				// merge subsequent variables into this class (skipping *vt, already there)
-				while ( ++vt != c.vars.end() ) {
-					auto st = internal_lookup( *vt );
-					if ( st == env.end() ) {
-						// unbound, safe to add if passes occurs
-						if ( r.type && occurs( r.type, *vt, *this ) ) return false;
-						r.vars.insert( *vt );
-					} else if ( st != rt ) {
-						// bound, but not to the same class
-						if ( ! mergeClasses( rt, st, openVars, indexer ) ) return false;
-					}   // ignore bound into the same class
-				}
-			} else {  // no variables in c bound; just copy up
-				env.push_back( c );
-			}
-		}
-
-		// merged all classes
-		return true;
-	}
-
-	void TypeEnvironment::extractOpenVars( OpenVarSet &openVars ) const {
-		for ( ClassList::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {
-			for ( std::set< std::string >::const_iterator var = eqvClass->vars.begin(); var != eqvClass->vars.end(); ++var ) {
-				openVars[ *var ] = eqvClass->data;
-			} // for
-		} // for
-	}
-
-	void TypeEnvironment::addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars ) {
-		for ( const EqvClass& c : actualEnv ) {
-			EqvClass c2 = c;
-			c2.allowWidening = false;
-			for ( const std::string& var : c2.vars ) {
-				openVars[ var ] = c2.data;
-			}
-			env.push_back( std::move(c2) );
-		}
-	}
-
-	bool isFtype( const Type * type ) {
-		if ( dynamic_cast< const FunctionType * >( type ) ) {
-			return true;
-		} else if ( const TypeInstType *typeInst = dynamic_cast< const TypeInstType * >( type ) ) {
-			return typeInst->get_isFtype();
-		} // if
-		return false;
-	}
-
-	bool tyVarCompatible( const TypeDecl::Data & data, const Type * type ) {
-		switch ( data.kind ) {
-		  case TypeDecl::Dtype:
-			// to bind to an object type variable, the type must not be a function type.
-			// if the type variable is specified to be a complete type then the incoming
-			// type must also be complete
-			// xxx - should this also check that type is not a tuple type and that it's not a ttype?
-			return ! isFtype( type ) && (! data.isComplete || type->isComplete() );
-		  case TypeDecl::Ftype:
-			return isFtype( type );
-		  case TypeDecl::Ttype:
-			// ttype unifies with any tuple type
-			return dynamic_cast< const TupleType * >( type ) || Tuples::isTtype( type );
-		  default:
-			assertf(false, "Unhandled tyvar kind: %d", data.kind);
-		} // switch
-		return false;
-	}
-
-	bool TypeEnvironment::bindVar( const TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
-
-		// remove references from other, so that type variables can only bind to value types
-		bindTo = bindTo->stripReferences();
-		OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
-		assert( tyvar != openVars.end() );
-		if ( ! tyVarCompatible( tyvar->second, bindTo ) ) {
-			return false;
-		} // if
-		if ( occurs( bindTo, typeInst->get_name(), *this ) ) {
-			return false;
-		} // if
-		auto curClass = internal_lookup( typeInst->get_name() );
-		if ( curClass != env.end() ) {
-			if ( curClass->type ) {
-				Type *common = 0;
-				// attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
-				std::unique_ptr< Type > newType( curClass->type->clone() );
-				newType->tq = typeInst->tq;
-				if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widen & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
-					if ( common ) {
-						common->get_qualifiers() = Type::Qualifiers{};
-						curClass->set_type( common );
-					} // if
-				} else return false;
-			} else {
-				Type* newType = bindTo->clone();
-				newType->get_qualifiers() = Type::Qualifiers{};
-				curClass->set_type( newType );
-				curClass->allowWidening = widen.first && widen.second;
-			} // if
-		} else {
-			EqvClass newClass;
-			newClass.vars.insert( typeInst->get_name() );
-			newClass.type = bindTo->clone();
-			newClass.type->get_qualifiers() = Type::Qualifiers();
-			newClass.allowWidening = widen.first && widen.second;
-			newClass.data = data;
-			env.push_back( std::move(newClass) );
-		} // if
-		return true;
-	}
-
-	bool TypeEnvironment::bindVarToVar( const TypeInstType * var1, const TypeInstType * var2,
-			TypeDecl::Data && data, AssertionSet &need, AssertionSet &have,
-			const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
-
-		auto class1 = internal_lookup( var1->get_name() );
-		auto class2 = internal_lookup( var2->get_name() );
-
-		// exit early if variables already bound together
-		if ( class1 != env.end() && class1 == class2 ) {
-			class1->allowWidening &= widen;
-			return true;
-		}
-
-		bool widen1 = false, widen2 = false;
-		const Type *type1 = nullptr, *type2 = nullptr;
-
-		// check for existing bindings, perform occurs check
-		if ( class1 != env.end() ) {
-			if ( class1->type ) {
-				if ( occurs( class1->type, var2->get_name(), *this ) ) return false;
-				type1 = class1->type;
-			} // if
-			widen1 = widen.first && class1->allowWidening;
-		} // if
-		if ( class2 != env.end() ) {
-			if ( class2->type ) {
-				if ( occurs( class2->type, var1->get_name(), *this ) ) return false;
-				type2 = class2->type;
-			} // if
-			widen2 = widen.second && class2->allowWidening;
-		} // if
-
-		if ( type1 && type2 ) {
-			// both classes bound, merge if bound types can be unified
-			std::unique_ptr<Type> newType1{ type1->clone() }, newType2{ type2->clone() };
-			WidenMode newWidenMode{ widen1, widen2 };
-			Type *common = 0;
-			if ( unifyInexact( newType1.get(), newType2.get(), *this, need, have, openVars, newWidenMode, indexer, common ) ) {
-				class1->vars.insert( class2->vars.begin(), class2->vars.end() );
-				class1->allowWidening = widen1 && widen2;
-				if ( common ) {
-					common->get_qualifiers() = Type::Qualifiers{};
-					class1->set_type( common );
-				}
-				class1->data.isComplete |= data.isComplete;
-				env.erase( class2 );
-			} else return false;
-		} else if ( class1 != env.end() && class2 != env.end() ) {
-			// both classes exist, at least one unbound, merge unconditionally
-			if ( type1 ) {
-				class1->vars.insert( class2->vars.begin(), class2->vars.end() );
-				class1->allowWidening = widen1;
-				class1->data.isComplete |= data.isComplete;
-				env.erase( class2 );
-			} else {
-				class2->vars.insert( class1->vars.begin(), class1->vars.end() );
-				class2->allowWidening = widen2;
-				class2->data.isComplete |= data.isComplete;
-				env.erase( class1 );
-			} // if
-		} else if ( class1 != env.end() ) {
-			// var2 unbound, add to class1
-			class1->vars.insert( var2->get_name() );
-			class1->allowWidening = widen1;
-			class1->data.isComplete |= data.isComplete;
-		} else if ( class2 != env.end() ) {
-			// var1 unbound, add to class2
-			class2->vars.insert( var1->get_name() );
-			class2->allowWidening = widen2;
-			class2->data.isComplete |= data.isComplete;
-		} else {
-			// neither var bound, create new class
-			EqvClass newClass;
-			newClass.vars.insert( var1->get_name() );
-			newClass.vars.insert( var2->get_name() );
-			newClass.allowWidening = widen1 && widen2;
-			newClass.data = data;
-			env.push_back( std::move(newClass) );
-		} // if
-		return true;
-	}
-
-	void TypeEnvironment::forbidWidening() {
-		for ( EqvClass& c : env ) c.allowWidening = false;
-	}
-
-	std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ) {
-		env.print( out );
-		return out;
-	}
-} // namespace ResolvExpr
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/ResolvExpr/TypeEnvironment.h
===================================================================
--- src/ResolvExpr/TypeEnvironment.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,180 +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.
-//
-// TypeEnvironment.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 12:24:58 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri Jul 19 17:00:10 2019
-// Update Count     : 10
-//
-
-#pragma once
-
-#include <iostream>                    // for ostream
-#include <list>                        // for list, list<>::iterator, list<>...
-#include <map>						   // for map, map<>::value_compare
-#include <unordered_map>
-#include <set>						   // for set
-#include <string>                      // for string
-#include <utility>                     // for move, swap
-
-#include "WidenMode.h"                 // for WidenMode
-
-#include "SynTree/Declaration.h"       // for TypeDecl::Data, DeclarationWit...
-#include "SynTree/SynTree.h"           // for UniqueId
-#include "SynTree/Type.h"              // for Type, Type::ForallList
-#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
-
-namespace ResolvExpr {
-	// adding this comparison operator significantly improves assertion resolution run time for
-	// some cases. The current resolution algorithm's speed partially depends on the order of
-	// assertions. Assertions which have fewer possible matches should appear before
-	// assertions which have more possible matches. This seems to imply that this could
-	// be further improved by providing an indexer as an additional argument and ordering based
-	// on the number of matches of the same kind (object, function) for the names of the
-	// declarations.
-	//
-	// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this
-	// comparator.
-	//
-	// Note: since this compares pointers for position, minor changes in the source file that affect
-	// memory layout can alter compilation time in unpredictable ways. For example, the placement
-	// of a line directive can reorder type pointers with respect to each other so that assertions
-	// are seen in different orders, causing a potentially different number of unification calls
-	// when resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering
-	// line directives alone, so it would be nice to fix this comparison so that assertions compare
-	// more consistently. I've tried to modify this to compare on mangle name instead of type as
-	// the second comparator, but this causes some assertions to never be recorded. More
-	// investigation is needed.
-	struct AssertCompare {
-		bool operator()( const DeclarationWithType * d1, const DeclarationWithType * d2 ) const {
-			int cmp = d1->get_name().compare( d2->get_name() );
-			return cmp < 0 ||
-				( cmp == 0 && d1->get_type() < d2->get_type() );
-		}
-	};
-	struct AssertionSetValue {
-		bool isUsed;        ///< True if assertion needs to be resolved
-		UniqueId resnSlot;  ///< ID of slot assertion belongs to
-
-		AssertionSetValue() : isUsed(false), resnSlot(0) {}
-	};
-	typedef std::map< const DeclarationWithType *, AssertionSetValue, AssertCompare > AssertionSet;
-	typedef std::unordered_map< std::string, TypeDecl::Data > OpenVarSet;
-
-	/// merges one set of open vars into another
-	static inline void mergeOpenVars( OpenVarSet& dst, const OpenVarSet& src ) {
-		for ( const auto& entry : src ) { dst[ entry.first ] = entry.second; }
-	}
-
-	void printAssertionSet( const AssertionSet &, std::ostream &, int indent = 0 );
-	void printOpenVarSet( const OpenVarSet &, std::ostream &, int indent = 0 );
-
-	struct EqvClass {
-		std::set< std::string > vars;
-		Type * type;
-		bool allowWidening;
-		TypeDecl::Data data;
-
-		void initialize( const EqvClass &src, EqvClass &dest );
-		void initialize( const EqvClass &src, EqvClass &dest, const Type *ty );
-		EqvClass();
-		EqvClass( const EqvClass &other );
-		EqvClass( const EqvClass &other, const Type *ty );
-		EqvClass( EqvClass &&other );
-		EqvClass &operator=( const EqvClass &other );
-		EqvClass &operator=( EqvClass &&other );
-		~EqvClass();
-		void print( std::ostream &os, Indenter indent = {} ) const;
-
-		/// Takes ownership of `ty`, freeing old `type`
-		void set_type(Type* ty);
-	};
-
-	class TypeEnvironment {
-		using ClassList = std::list< EqvClass >;
-	  public:
-		const EqvClass* lookup( const std::string &var ) const;
-	  private:
-		void add( EqvClass &&eqvClass  );
-	  public:
-		void add( const Type::ForallList &tyDecls );
-		void add( const TypeSubstitution & sub );
-		template< typename SynTreeClass > int apply( SynTreeClass *&type ) const;
-		template< typename SynTreeClass > int applyFree( SynTreeClass *&type ) const;
-		void makeSubstitution( TypeSubstitution &result ) const;
-		bool isEmpty() const { return env.empty(); }
-		void print( std::ostream &os, Indenter indent = {} ) const;
-
-		/// Simply concatenate the second environment onto this one; no safety checks performed
-		void simpleCombine( const TypeEnvironment &second );
-
-	  private:
-		/// Unifies the type bound of to with the type bound of from, returning false if fails
-		bool mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer );
-
-		/// Merges two type classes from local environment, returning false if fails
-		bool mergeClasses( ClassList::iterator to, ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer );
-
-	  public:
-		/// Merges the second environment with this one, checking compatibility.
-		/// Returns false if fails, but does NOT roll back partial changes.
-		bool combine( const TypeEnvironment& second, OpenVarSet& openVars, const SymTab::Indexer& indexer );
-
-		void extractOpenVars( OpenVarSet &openVars ) const;
-		TypeEnvironment *clone() const { return new TypeEnvironment( *this ); }
-
-		/// Iteratively adds the environment of a new actual (with allowWidening = false),
-		/// and extracts open variables.
-		void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars );
-
-		/// Binds the type class represented by `typeInst` to the type `bindTo`; will add
-		/// the class if needed. Returns false on failure.
-		bool bindVar( const TypeInstType * typeInst, Type * bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
-
-		/// Binds the type classes represented by `var1` and `var2` together; will add
-		/// one or both classes if needed. Returns false on failure.
-		bool bindVarToVar( const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
-
-		/// Disallows widening for all bindings in the environment
-		void forbidWidening();
-
-		using iterator = ClassList::const_iterator;
-		iterator begin() const { return env.begin(); }
-		iterator end() const { return env.end(); }
-
-		auto size() const { return env.size(); }
-
-	  private:
-		ClassList env;
-
-		ClassList::iterator internal_lookup( const std::string &var );
-	};
-
-	template< typename SynTreeClass >
-	int TypeEnvironment::apply( SynTreeClass *&type ) const {
-		TypeSubstitution sub;
-		makeSubstitution( sub );
-		return sub.apply( type );
-	}
-
-	template< typename SynTreeClass >
-	int TypeEnvironment::applyFree( SynTreeClass *&type ) const {
-		TypeSubstitution sub;
-		makeSubstitution( sub );
-		return sub.applyFree( type );
-	}
-
-	std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env );
-} // namespace ResolvExpr
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/Unify.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -33,17 +33,8 @@
 #include "AST/TypeEnvironment.hpp"
 #include "Common/Eval.h"            // for eval
-#include "Common/PassVisitor.h"     // for PassVisitor
 #include "CommonType.hpp"           // for commonType
 #include "FindOpenVars.h"           // for findOpenVars
 #include "SpecCost.hpp"             // for SpecCost
-#include "SynTree/LinkageSpec.h"    // for C
-#include "SynTree/Constant.h"       // for Constant
-#include "SynTree/Declaration.h"    // for TypeDecl, TypeDecl::Data, Declarati...
-#include "SynTree/Expression.h"     // for TypeExpr, Expression, ConstantExpr
-#include "SynTree/Mutator.h"        // for Mutator
-#include "SynTree/Type.h"           // for Type, TypeInstType, FunctionType
-#include "SynTree/Visitor.h"        // for Visitor
 #include "Tuples/Tuples.h"          // for isTtype
-#include "TypeEnvironment.h"        // for EqvClass, AssertionSet, OpenVarSet
 #include "typeops.h"                // for flatten, occurs
 
@@ -52,101 +43,7 @@
 }
 
-namespace SymTab {
-	class Indexer;
-}  // namespace SymTab
-
 // #define DEBUG
 
 namespace ResolvExpr {
-
-// Template Helpers:
-template< typename Iterator1, typename Iterator2 >
-bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) {
-	for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
-		Type *commonType = 0;
-		if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
-			return false;
-		} // if
-		commonTypes.push_back( commonType );
-	} // for
-	return ( list1Begin == list1End && list2Begin == list2End );
-}
-
-template< typename Iterator1, typename Iterator2 >
-bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
-	std::list< Type* > commonTypes;
-	if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions,  openVars, indexer, commonTypes ) ) {
-		deleteAll( commonTypes );
-		return true;
-	} else {
-		return false;
-	} // if
-}
-
-	struct Unify_old : public WithShortCircuiting {
-		Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
-
-		bool get_result() const { return result; }
-
-		void previsit( BaseSyntaxNode * ) { visit_children = false; }
-
-		void postvisit( VoidType * voidType );
-		void postvisit( BasicType * basicType );
-		void postvisit( PointerType * pointerType );
-		void postvisit( ArrayType * arrayType );
-		void postvisit( ReferenceType * refType );
-		void postvisit( FunctionType * functionType );
-		void postvisit( StructInstType * aggregateUseType );
-		void postvisit( UnionInstType * aggregateUseType );
-		void postvisit( EnumInstType * aggregateUseType );
-		void postvisit( TraitInstType * aggregateUseType );
-		void postvisit( TypeInstType * aggregateUseType );
-		void postvisit( TupleType * tupleType );
-		void postvisit( VarArgsType * varArgsType );
-		void postvisit( ZeroType * zeroType );
-		void postvisit( OneType * oneType );
-
-	  private:
-		template< typename RefType > void handleRefType( RefType *inst, Type *other );
-		template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );
-
-		bool result;
-		Type *type2;				// inherited
-		TypeEnvironment &env;
-		AssertionSet &needAssertions;
-		AssertionSet &haveAssertions;
-		const OpenVarSet &openVars;
-		WidenMode widen;
-		const SymTab::Indexer &indexer;
-	};
-
-	/// Attempts an inexact unification of type1 and type2.
-	/// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers)
-	bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
-	bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
-
-	bool unifyExact(
-		const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
-		ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
-		WidenMode widen );
-
-	bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
-		TypeEnvironment newEnv;
-		OpenVarSet openVars, closedVars; // added closedVars
-		AssertionSet needAssertions, haveAssertions;
-		Type * newFirst = first->clone(), * newSecond = second->clone();
-		env.apply( newFirst );
-		env.apply( newSecond );
-
-		// do we need to do this? Seems like we do, types should be able to be compatible if they
-		// have free variables that can unify
-		findOpenVars( newFirst, openVars, closedVars, needAssertions, haveAssertions, false );
-		findOpenVars( newSecond, openVars, closedVars, needAssertions, haveAssertions, true );
-
-		bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-		delete newFirst;
-		delete newSecond;
-		return result;
-	}
 
 	bool typesCompatible(
@@ -165,20 +62,4 @@
 
 		return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() );
-	}
-
-	bool typesCompatibleIgnoreQualifiers( const Type * first, const Type * second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
-		TypeEnvironment newEnv;
-		OpenVarSet openVars;
-		AssertionSet needAssertions, haveAssertions;
-		Type *newFirst = first->clone(), *newSecond = second->clone();
-		env.apply( newFirst );
-		env.apply( newSecond );
-		newFirst->get_qualifiers() = Type::Qualifiers();
-		newSecond->get_qualifiers() = Type::Qualifiers();
-
-		bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-		delete newFirst;
-		delete newSecond;
-		return result;
 	}
 
@@ -220,526 +101,12 @@
 	}
 
-	bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
-		OpenVarSet closedVars;
-		findOpenVars( type1, openVars, closedVars, needAssertions, haveAssertions, false );
-		findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true );
-		Type *commonType = 0;
-		if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) {
-			if ( commonType ) {
-				delete commonType;
-			} // if
-			return true;
-		} else {
-			return false;
-		} // if
-	}
-
-	bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType ) {
-		OpenVarSet closedVars;
-		findOpenVars( type1, openVars, closedVars, needAssertions, haveAssertions, false );
-		findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true );
-		return unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType );
-	}
-
-	bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
-#ifdef DEBUG
-		TypeEnvironment debugEnv( env );
-#endif
-		if ( type1->get_qualifiers() != type2->get_qualifiers() ) {
-			return false;
-		}
-
-		bool result;
-		TypeInstType *var1 = dynamic_cast< TypeInstType* >( type1 );
-		TypeInstType *var2 = dynamic_cast< TypeInstType* >( type2 );
-		OpenVarSet::const_iterator entry1, entry2;
-		if ( var1 ) {
-			entry1 = openVars.find( var1->get_name() );
-		} // if
-		if ( var2 ) {
-			entry2 = openVars.find( var2->get_name() );
-		} // if
-		bool isopen1 = var1 && ( entry1 != openVars.end() );
-		bool isopen2 = var2 && ( entry2 != openVars.end() );
-
-		if ( isopen1 && isopen2 ) {
-			if ( entry1->second.kind != entry2->second.kind ) {
-				result = false;
-			} else {
-				result = env.bindVarToVar(
-					var1, var2, TypeDecl::Data{ entry1->second, entry2->second }, needAssertions,
-					haveAssertions, openVars, widen, indexer );
-			}
-		} else if ( isopen1 ) {
-			result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widen, indexer );
-		} else if ( isopen2 ) { // TODO: swap widen values in call, since type positions are flipped?
-			result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widen, indexer );
-		} else {
-			PassVisitor<Unify_old> comparator( type2, env, needAssertions, haveAssertions, openVars, widen, indexer );
-			type1->accept( comparator );
-			result = comparator.pass.get_result();
-		} // if
-#ifdef DEBUG
-		std::cerr << "============ unifyExact" << std::endl;
-		std::cerr << "type1 is ";
-		type1->print( std::cerr );
-		std::cerr << std::endl << "type2 is ";
-		type2->print( std::cerr );
-		std::cerr << std::endl << "openVars are ";
-		printOpenVarSet( openVars, std::cerr, 8 );
-		std::cerr << std::endl << "input env is " << std::endl;
-		debugEnv.print( std::cerr, 8 );
-		std::cerr << std::endl << "result env is " << std::endl;
-		env.print( std::cerr, 8 );
-		std::cerr << "result is " << result << std::endl;
-#endif
-		return result;
-	}
-
-	bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
-		return unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-	}
-
-	bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ) {
-		Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers();
-		type1->get_qualifiers() = Type::Qualifiers();
-		type2->get_qualifiers() = Type::Qualifiers();
-		bool result;
-#ifdef DEBUG
-		std::cerr << "unifyInexact type 1 is ";
-		type1->print( std::cerr );
-		std::cerr << " type 2 is ";
-		type2->print( std::cerr );
-		std::cerr << std::endl;
-#endif
-		if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen, indexer ) ) {
-#ifdef DEBUG
-			std::cerr << "unifyInexact: no exact unification found" << std::endl;
-#endif
-			if ( ( common = commonType( type1, type2, widen.first, widen.second, indexer, env, openVars ) ) ) {
-				common->tq = tq1.unify( tq2 );
-#ifdef DEBUG
-				std::cerr << "unifyInexact: common type is ";
-				common->print( std::cerr );
-				std::cerr << std::endl;
-#endif
-				result = true;
-			} else {
-#ifdef DEBUG
-				std::cerr << "unifyInexact: no common type found" << std::endl;
-#endif
-				result = false;
-			} // if
-		} else {
-			if ( tq1 != tq2 ) {
-				if ( ( tq1 > tq2 || widen.first ) && ( tq2 > tq1 || widen.second ) ) {
-					common = type1->clone();
-					common->tq = tq1.unify( tq2 );
-					result = true;
-				} else {
-					result = false;
-				} // if
-			} else {
-				common = type1->clone();
-				common->tq = tq1.unify( tq2 );
-				result = true;
-			} // if
-		} // if
-		type1->get_qualifiers() = tq1;
-		type2->get_qualifiers() = tq2;
-		return result;
-	}
-
-	Unify_old::Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer )
-		: result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen( widen ), indexer( indexer ) {
-	}
-
-	void Unify_old::postvisit( __attribute__((unused)) VoidType *voidType) {
-		result = dynamic_cast< VoidType* >( type2 );
-	}
-
-	void Unify_old::postvisit(BasicType *basicType) {
-		if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
-			result = basicType->get_kind() == otherBasic->get_kind();
-		} // if
-	}
-
-	void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) {
-		AssertionSet::iterator i = assertions.find( assert );
-		if ( i != assertions.end() ) {
-			i->second.isUsed = true;
-		} // if
-	}
-
-	void markAssertions( AssertionSet &assertion1, AssertionSet &assertion2, Type *type ) {
-		for ( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
-			for ( std::list< DeclarationWithType* >::const_iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
-				markAssertionSet( assertion1, *assert );
-				markAssertionSet( assertion2, *assert );
-			} // for
-		} // for
-	}
-
-	void Unify_old::postvisit(PointerType *pointerType) {
-		if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
-			result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-			markAssertions( haveAssertions, needAssertions, pointerType );
-			markAssertions( haveAssertions, needAssertions, otherPointer );
-		} // if
-	}
-
-	void Unify_old::postvisit(ReferenceType *refType) {
-		if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
-			result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-			markAssertions( haveAssertions, needAssertions, refType );
-			markAssertions( haveAssertions, needAssertions, otherRef );
-		} // if
-	}
-
-	void Unify_old::postvisit(ArrayType *arrayType) {
-		ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
-		// to unify, array types must both be VLA or both not VLA
-		// and must both have a dimension expression or not have a dimension
-		if ( otherArray && arrayType->get_isVarLen() == otherArray->get_isVarLen() ) {
-
-			if ( ! arrayType->get_isVarLen() && ! otherArray->get_isVarLen() &&
-				arrayType->get_dimension() != 0 && otherArray->get_dimension() != 0 ) {
-				ConstantExpr * ce1 = dynamic_cast< ConstantExpr * >( arrayType->get_dimension() );
-				ConstantExpr * ce2 = dynamic_cast< ConstantExpr * >( otherArray->get_dimension() );
-				// see C11 Reference Manual 6.7.6.2.6
-				// two array types with size specifiers that are integer constant expressions are
-				// compatible if both size specifiers have the same constant value
-				if ( ce1 && ce2 ) {
-					Constant * c1 = ce1->get_constant();
-					Constant * c2 = ce2->get_constant();
-
-					if ( c1->get_value() != c2->get_value() ) {
-						// does not unify if the dimension is different
-						return;
-					}
-				}
-			}
-
-			result = unifyExact( arrayType->get_base(), otherArray->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-		} // if
-	}
-
-	template< typename Iterator, typename Func >
-	std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end, Func & toType ) {
-		std::list< Type * > types;
-		for ( ; begin != end; ++begin ) {
-			// it's guaranteed that a ttype variable will be bound to a flat tuple, so ensure that this results in a flat tuple
-			flatten( toType( *begin ), back_inserter( types ) );
-		}
-		return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) );
-	}
-
-	template< typename Iterator1, typename Iterator2 >
-	bool unifyTypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
-		auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); };
-		for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
-			Type * t1 = (*list1Begin)->get_type();
-			Type * t2 = (*list2Begin)->get_type();
-			bool isTtype1 = Tuples::isTtype( t1 );
-			bool isTtype2 = Tuples::isTtype( t2 );
-			// xxx - assumes ttype must be last parameter
-			// xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases.
-			if ( isTtype1 && ! isTtype2 ) {
-				// combine all of the things in list2, then unify
-				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-			} else if ( isTtype2 && ! isTtype1 ) {
-				// combine all of the things in list1, then unify
-				return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-			} else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
-				return false;
-			} // if
-		} // for
-		// may get to the end of one argument list before the end of the other. This is only okay when the other is a ttype
-		if ( list1Begin != list1End ) {
-			// try unifying empty tuple type with ttype
-			Type * t1 = (*list1Begin)->get_type();
-			if ( Tuples::isTtype( t1 ) ) {
-				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-			} else return false;
-		} else if ( list2Begin != list2End ) {
-			// try unifying empty tuple type with ttype
-			Type * t2 = (*list2Begin)->get_type();
-			if ( Tuples::isTtype( t2 ) ) {
-				return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-			} else return false;
-		} else {
-			return true;
-		} // if
-	}
-
-	/// Finds ttypes and replaces them with their expansion, if known.
-	/// This needs to be done so that satisfying ttype assertions is easier.
-	/// If this isn't done then argument lists can have wildly different
-	/// size and structure, when they should be compatible.
-	struct TtypeExpander_old : public WithShortCircuiting {
-		TypeEnvironment & tenv;
-		TtypeExpander_old( TypeEnvironment & tenv ) : tenv( tenv ) {}
-		void premutate( TypeInstType * ) { visit_children = false; }
-		Type * postmutate( TypeInstType * typeInst ) {
-			if ( const EqvClass *eqvClass = tenv.lookup( typeInst->get_name() ) ) {
-				// expand ttype parameter into its actual type
-				if ( eqvClass->data.kind == TypeDecl::Ttype && eqvClass->type ) {
-					delete typeInst;
-					return eqvClass->type->clone();
-				}
-			}
-			return typeInst;
-		}
-	};
-
-	/// flattens a list of declarations, so that each tuple type has a single declaration.
-	/// makes use of TtypeExpander to ensure ttypes are flat as well.
-	void flattenList( std::list< DeclarationWithType * > src, std::list< DeclarationWithType * > & dst, TypeEnvironment & env ) {
-		dst.clear();
-		for ( DeclarationWithType * dcl : src ) {
-			PassVisitor<TtypeExpander_old> expander( env );
-			dcl->acceptMutator( expander );
-			std::list< Type * > types;
-			flatten( dcl->get_type(), back_inserter( types ) );
-			for ( Type * t : types ) {
-				// outermost const, volatile, _Atomic qualifiers in parameters should not play a role in the unification of function types, since they do not determine whether a function is callable.
-				// Note: MUST consider at least mutex qualifier, since functions can be overloaded on outermost mutex and a mutex function has different requirements than a non-mutex function.
-				t->get_qualifiers() -= Type::Qualifiers(Type::Const | Type::Volatile | Type::Atomic);
-
-				dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) );
-			}
-			delete dcl;
-		}
-	}
-
-	void Unify_old::postvisit(FunctionType *functionType) {
-		FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
-		if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
-			// flatten the parameter lists for both functions so that tuple structure
-			// doesn't affect unification. Must be a clone so that the types don't change.
-			std::unique_ptr<FunctionType> flatFunc( functionType->clone() );
-			std::unique_ptr<FunctionType> flatOther( otherFunction->clone() );
-			flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env );
-			flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env );
-
-			// sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors
-			if (
-					(flatFunc->parameters.size() == flatOther->parameters.size() &&
-						flatFunc->returnVals.size() == flatOther->returnVals.size())
-					|| flatFunc->isTtype()
-					|| flatOther->isTtype()
-			) {
-				if ( unifyTypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
-					if ( unifyTypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
-
-						// the original types must be used in mark assertions, since pointer comparisons are used
-						markAssertions( haveAssertions, needAssertions, functionType );
-						markAssertions( haveAssertions, needAssertions, otherFunction );
-
-						result = true;
-					} // if
-				} // if
-			} // if
-		} // if
-	}
-
-	template< typename RefType >
-	void Unify_old::handleRefType( RefType *inst, Type *other ) {
-		// check that other type is compatible and named the same
-		RefType *otherStruct = dynamic_cast< RefType* >( other );
-		result = otherStruct && inst->name == otherStruct->name;
-	}
-
-	template< typename RefType >
-	void Unify_old::handleGenericRefType( RefType *inst, Type *other ) {
-		// Check that other type is compatible and named the same
-		handleRefType( inst, other );
-		if ( ! result ) return;
-		// Check that parameters of types unify, if any
-		std::list< Expression* > params = inst->parameters;
-		std::list< Expression* > otherParams = ((RefType*)other)->parameters;
-
-		std::list< Expression* >::const_iterator it = params.begin(), jt = otherParams.begin();
-		for ( ; it != params.end() && jt != otherParams.end(); ++it, ++jt ) {
-			TypeExpr *param = dynamic_cast< TypeExpr* >(*it);
-			assertf(param, "Aggregate parameters should be type expressions");
-			TypeExpr *otherParam = dynamic_cast< TypeExpr* >(*jt);
-			assertf(otherParam, "Aggregate parameters should be type expressions");
-
-			Type* paramTy = param->get_type();
-			Type* otherParamTy = otherParam->get_type();
-
-			bool tupleParam = Tuples::isTtype( paramTy );
-			bool otherTupleParam = Tuples::isTtype( otherParamTy );
-
-			if ( tupleParam && otherTupleParam ) {
-				++it; ++jt;  // skip ttype parameters for break
-			} else if ( tupleParam ) {
-				// bundle other parameters into tuple to match
-				std::list< Type * > binderTypes;
-
-				do {
-					binderTypes.push_back( otherParam->get_type()->clone() );
-					++jt;
-
-					if ( jt == otherParams.end() ) break;
-
-					otherParam = dynamic_cast< TypeExpr* >(*jt);
-					assertf(otherParam, "Aggregate parameters should be type expressions");
-				} while (true);
-
-				otherParamTy = new TupleType{ paramTy->get_qualifiers(), binderTypes };
-				++it;  // skip ttype parameter for break
-			} else if ( otherTupleParam ) {
-				// bundle parameters into tuple to match other
-				std::list< Type * > binderTypes;
-
-				do {
-					binderTypes.push_back( param->get_type()->clone() );
-					++it;
-
-					if ( it == params.end() ) break;
-
-					param = dynamic_cast< TypeExpr* >(*it);
-					assertf(param, "Aggregate parameters should be type expressions");
-				} while (true);
-
-				paramTy = new TupleType{ otherParamTy->get_qualifiers(), binderTypes };
-				++jt;  // skip ttype parameter for break
-			}
-
-			if ( ! unifyExact( paramTy, otherParamTy, env, needAssertions, haveAssertions, openVars, WidenMode(false, false), indexer ) ) {
-				result = false;
-				return;
-			}
-
-			// ttype parameter should be last
-			if ( tupleParam || otherTupleParam ) break;
-		}
-		result = ( it == params.end() && jt == otherParams.end() );
-	}
-
-	void Unify_old::postvisit(StructInstType *structInst) {
-		handleGenericRefType( structInst, type2 );
-	}
-
-	void Unify_old::postvisit(UnionInstType *unionInst) {
-		handleGenericRefType( unionInst, type2 );
-	}
-
-	void Unify_old::postvisit(EnumInstType *enumInst) {
-		handleRefType( enumInst, type2 );
-	}
-
-	void Unify_old::postvisit(TraitInstType *contextInst) {
-		handleRefType( contextInst, type2 );
-	}
-
-	void Unify_old::postvisit(TypeInstType *typeInst) {
-		assert( openVars.find( typeInst->get_name() ) == openVars.end() );
-		TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 );
-		if ( otherInst && typeInst->get_name() == otherInst->get_name() ) {
-			result = true;
-///   } else {
-///     NamedTypeDecl *nt = indexer.lookupType( typeInst->get_name() );
-///     if ( nt ) {
-///       TypeDecl *type = dynamic_cast< TypeDecl* >( nt );
-///       assert( type );
-///       if ( type->get_base() ) {
-///         result = unifyExact( type->get_base(), typeInst, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-///       }
-///     }
-		} // if
-	}
-
-	template< typename Iterator1, typename Iterator2 >
-	bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
-		auto get_type = [](Type * t) { return t; };
-		for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
-			Type * t1 = *list1Begin;
-			Type * t2 = *list2Begin;
-			bool isTtype1 = Tuples::isTtype( t1 );
-			bool isTtype2 = Tuples::isTtype( t2 );
-			// xxx - assumes ttype must be last parameter
-			// xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases.
-			if ( isTtype1 && ! isTtype2 ) {
-				// combine all of the things in list2, then unify
-				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-			} else if ( isTtype2 && ! isTtype1 ) {
-				// combine all of the things in list1, then unify
-				return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-			} else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
-				return false;
-			} // if
-
-		} // for
-		if ( list1Begin != list1End ) {
-			// try unifying empty tuple type with ttype
-			Type * t1 = *list1Begin;
-			if ( Tuples::isTtype( t1 ) ) {
-				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-			} else return false;
-		} else if ( list2Begin != list2End ) {
-			// try unifying empty tuple type with ttype
-			Type * t2 = *list2Begin;
-			if ( Tuples::isTtype( t2 ) ) {
-				return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-			} else return false;
-		} else {
-			return true;
-		} // if
-	}
-
-	void Unify_old::postvisit(TupleType *tupleType) {
-		if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
-			std::unique_ptr<TupleType> flat1( tupleType->clone() );
-			std::unique_ptr<TupleType> flat2( otherTuple->clone() );
-			std::list<Type *> types1, types2;
-
-			PassVisitor<TtypeExpander_old> expander( env );
-			flat1->acceptMutator( expander );
-			flat2->acceptMutator( expander );
-
-			flatten( flat1.get(), back_inserter( types1 ) );
-			flatten( flat2.get(), back_inserter( types2 ) );
-
-			result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, indexer );
-		} // if
-	}
-
-	void Unify_old::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
-		result = dynamic_cast< VarArgsType* >( type2 );
-	}
-
-	void Unify_old::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
-		result = dynamic_cast< ZeroType* >( type2 );
-	}
-
-	void Unify_old::postvisit( __attribute__((unused)) OneType *oneType ) {
-		result = dynamic_cast< OneType* >( type2 );
-	}
-
-	Type * extractResultType( FunctionType * function ) {
-		if ( function->get_returnVals().size() == 0 ) {
-			return new VoidType( Type::Qualifiers() );
-		} else if ( function->get_returnVals().size() == 1 ) {
-			return function->get_returnVals().front()->get_type()->clone();
-		} else {
-			std::list< Type * > types;
-			for ( DeclarationWithType * decl : function->get_returnVals() ) {
-				types.push_back( decl->get_type()->clone() );
-			} // for
-			return new TupleType( Type::Qualifiers(), types );
-		}
-	}
-
 	namespace {
 				/// Replaces ttype variables with their bound types.
 		/// If this isn't done when satifying ttype assertions, then argument lists can have
 		/// different size and structure when they should be compatible.
-		struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor {
+		struct TtypeExpander : public ast::WithShortCircuiting, public ast::PureVisitor {
 			ast::TypeEnvironment & tenv;
 
-			TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}
+			TtypeExpander( ast::TypeEnvironment & env ) : tenv( env ) {}
 
 			const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
@@ -761,5 +128,5 @@
 		dst.reserve( src.size() );
 		for ( const auto & d : src ) {
-			ast::Pass<TtypeExpander_new> expander{ env };
+			ast::Pass<TtypeExpander> expander{ env };
 			// TtypeExpander pass is impure (may mutate nodes in place)
 			// need to make nodes shared to prevent accidental mutation
@@ -901,5 +268,5 @@
 	}
 
-	class Unify_new final : public ast::WithShortCircuiting {
+	class Unify final : public ast::WithShortCircuiting {
 		const ast::Type * type2;
 		ast::TypeEnvironment & tenv;
@@ -912,5 +279,5 @@
 		bool result;
 
-		Unify_new(
+		Unify(
 			const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need,
 			ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen )
@@ -1239,5 +606,5 @@
 			if ( ! tuple2 ) return;
 
-			ast::Pass<TtypeExpander_new> expander{ tenv };
+			ast::Pass<TtypeExpander> expander{ tenv };
 
 			const ast::Type * flat = tuple->accept( expander );
@@ -1267,5 +634,6 @@
 	};
 
-	// size_t Unify_new::traceId = Stats::Heap::new_stacktrace_id("Unify_new");
+	// size_t Unify::traceId = Stats::Heap::new_stacktrace_id("Unify");
+
 	bool unify(
 			const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
@@ -1311,5 +679,5 @@
 			return env.bindVar( var2, type1, ast::TypeData{var2->base}, need, have, open, widen );
 		} else {
-			return ast::Pass<Unify_new>::read(
+			return ast::Pass<Unify>::read(
 				type1, type2, env, need, have, open, widen );
 		}
Index: src/ResolvExpr/Unify.h
===================================================================
--- src/ResolvExpr/Unify.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/Unify.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -20,14 +20,5 @@
 #include "AST/Node.hpp"             // for ptr
 #include "AST/TypeEnvironment.hpp"  // for TypeEnvironment, AssertionSet, OpenVarSet
-#include "Common/utility.h"       // for deleteAll
-#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data
-#include "TypeEnvironment.h"      // for AssertionSet, OpenVarSet
 #include "WidenMode.h"              // for WidenMode
-
-class Type;
-class TypeInstType;
-namespace SymTab {
-	class Indexer;
-}
 
 namespace ast {
@@ -37,22 +28,4 @@
 
 namespace ResolvExpr {
-
-bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
-bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
-bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
-bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
-
-bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
-bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
-
-inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
-	TypeEnvironment env;
-	return typesCompatible( t1, t2, indexer, env );
-}
-
-inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
-	TypeEnvironment env;
-	return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
-}
 
 bool unify(
@@ -85,7 +58,4 @@
 	const ast::TypeEnvironment & env = {} );
 
-/// Creates the type represented by the list of returnVals in a FunctionType.
-/// The caller owns the return value.
-Type * extractResultType( FunctionType * functionType );
 /// Creates or extracts the type represented by returns in a `FunctionType`.
 ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func );
Index: src/ResolvExpr/module.mk
===================================================================
--- src/ResolvExpr/module.mk	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/module.mk	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -18,8 +18,4 @@
       ResolvExpr/AdjustExprType.cc \
       ResolvExpr/AdjustExprType.hpp \
-      ResolvExpr/Alternative.cc \
-      ResolvExpr/AlternativeFinder.cc \
-      ResolvExpr/AlternativeFinder.h \
-      ResolvExpr/Alternative.h \
       ResolvExpr/Candidate.cpp \
       ResolvExpr/CandidateFinder.cpp \
@@ -35,11 +31,8 @@
       ResolvExpr/CurrentObject.cc \
       ResolvExpr/CurrentObject.h \
-      ResolvExpr/ExplodedActual.cc \
-      ResolvExpr/ExplodedActual.h \
       ResolvExpr/ExplodedArg.cpp \
       ResolvExpr/ExplodedArg.hpp \
       ResolvExpr/FindOpenVars.cc \
       ResolvExpr/FindOpenVars.h \
-      ResolvExpr/Occurs.cc \
       ResolvExpr/PolyCost.cc \
       ResolvExpr/PolyCost.hpp \
@@ -50,6 +43,4 @@
       ResolvExpr/RenameVars.cc \
       ResolvExpr/RenameVars.h \
-      ResolvExpr/ResolveAssertions.cc \
-      ResolvExpr/ResolveAssertions.h \
       ResolvExpr/Resolver.cc \
       ResolvExpr/Resolver.h \
@@ -61,6 +52,4 @@
       ResolvExpr/SpecCost.cc \
       ResolvExpr/SpecCost.hpp \
-      ResolvExpr/TypeEnvironment.cc \
-      ResolvExpr/TypeEnvironment.h \
       ResolvExpr/typeops.h \
       ResolvExpr/Unify.cc \
@@ -69,6 +58,4 @@
 
 SRC += $(SRC_RESOLVEXPR) \
-	ResolvExpr/AlternativePrinter.cc \
-	ResolvExpr/AlternativePrinter.h \
 	ResolvExpr/CandidatePrinter.cpp \
 	ResolvExpr/CandidatePrinter.hpp \
Index: src/ResolvExpr/typeops.h
===================================================================
--- src/ResolvExpr/typeops.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/ResolvExpr/typeops.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -19,9 +19,4 @@
 
 #include "AST/Type.hpp"
-#include "SynTree/Type.h"
-
-namespace SymTab {
-	class Indexer;
-}
 
 namespace ResolvExpr {
@@ -52,29 +47,4 @@
 			std::copy( i.begin(), i.end(), inserter );
 			*out++ = result;
-		}
-	}
-
-	// in Occurs.cc
-	bool occurs( const Type * type, const std::string & varName, const TypeEnvironment & env );
-	// new AST version in TypeEnvironment.cpp (only place it was used in old AST)
-
-	template<typename Iter>
-	bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment & env ) {
-		while ( begin != end ) {
-			if ( occurs( ty, *begin, env ) ) return true;
-			++begin;
-		}
-		return false;
-	}
-
-	/// flatten tuple type into list of types
-	template< typename OutputIterator >
-	void flatten( Type * type, OutputIterator out ) {
-		if ( TupleType * tupleType = dynamic_cast< TupleType * >( type ) ) {
-			for ( Type * t : tupleType->get_types() ) {
-				flatten( t, out );
-			}
-		} else {
-			*out++ = type->clone();
 		}
 	}
@@ -120,7 +90,4 @@
 		return tupleFromTypes( tys.begin(), tys.end() );
 	}
-
-	// in TypeEnvironment.cc
-	bool isFtype( const Type * type );
 } // namespace ResolvExpr
 
Index: c/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(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: c/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(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 df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/SymTab/Demangle.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -17,11 +17,10 @@
 #include <sstream>
 
+#include "AST/Pass.hpp"
+#include "AST/Type.hpp"
 #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
@@ -32,590 +31,293 @@
 #endif
 
+namespace Mangle {
+
 namespace {
-	struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting {
-		std::string typeString;
-		GenType( const std::string &typeString );
-
-		void previsit( BaseSyntaxNode * );
-		void postvisit( BaseSyntaxNode * );
-
-		void postvisit( FunctionType * funcType );
-		void postvisit( VoidType * voidType );
-		void postvisit( BasicType * basicType );
-		void postvisit( PointerType * pointerType );
-		void postvisit( ArrayType * arrayType );
-		void postvisit( ReferenceType * refType );
-		void postvisit( StructInstType * structInst );
-		void postvisit( UnionInstType * unionInst );
-		void postvisit( EnumInstType * enumInst );
-		void postvisit( TypeInstType * typeInst );
-		void postvisit( TupleType  * tupleType );
-		void postvisit( VarArgsType * varArgsType );
-		void postvisit( ZeroType * zeroType );
-		void postvisit( OneType * oneType );
-		void postvisit( GlobalScopeType * globalType );
-		void postvisit( QualifiedType * qualType );
-
-	  private:
-		void handleQualifiers( Type *type );
-		std::string handleGeneric( ReferenceToType * refType );
-		void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic );
-	};
-
-  std::string genDemangleType( Type * type, const std::string & baseString ) {
-		PassVisitor<GenType> gt( baseString );
-		assert( type );
-		type->accept( gt );
-		return gt.pass.typeString;
-  }
-
-	GenType::GenType( const std::string &typeString ) : typeString( typeString ) {}
-
-	// *** BaseSyntaxNode
-	void GenType::previsit( BaseSyntaxNode * ) {
-		// turn off automatic recursion for all nodes, to allow each visitor to
-		// precisely control the order in which its children are visited.
-		visit_children = false;
-	}
-
-	void GenType::postvisit( BaseSyntaxNode * node ) {
-		std::stringstream ss;
-		node->print( ss );
-		assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() );
-	}
-
-	void GenType::postvisit( VoidType * voidType ) {
-		typeString = "void " + typeString;
-		handleQualifiers( voidType );
-	}
-
-	void GenType::postvisit( BasicType * basicType ) {
-		BasicType::Kind kind = basicType->kind;
-		assert( 0 <= kind && kind < BasicType::NUMBER_OF_BASIC_TYPES );
-		typeString = std::string( BasicType::typeNames[kind] ) + " " + typeString;
-		handleQualifiers( basicType );
-	}
-
-	void GenType::genArray( const Type::Qualifiers & qualifiers, Type * base, Expression *dimension, bool isVarLen, bool ) {
-		std::ostringstream os;
-		if ( typeString != "" ) {
-			if ( typeString[ 0 ] == '*' ) {
-				os << "(" << typeString << ")";
-			} else {
-				os << typeString;
-			} // if
-		} // if
-		os << "[";
-
-		if ( qualifiers.is_const ) {
-			os << "const ";
-		} // if
-		if ( qualifiers.is_volatile ) {
-			os << "volatile ";
-		} // if
-		if ( qualifiers.is_restrict ) {
-			os << "__restrict ";
-		} // if
-		if ( qualifiers.is_atomic ) {
-			os << "_Atomic ";
-		} // if
-		if ( dimension != 0 ) {
-			// TODO: ???
-			// PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
-			// dimension->accept( cg );
-		} else if ( isVarLen ) {
-			// no dimension expression on a VLA means it came in with the * token
-			os << "*";
-		} // if
-		os << "]";
-
-		typeString = os.str();
-
-		base->accept( *visitor );
-	}
-
-	void GenType::postvisit( PointerType * pointerType ) {
-		assert( pointerType->base != 0);
-		if ( pointerType->get_isStatic() || pointerType->get_isVarLen() || pointerType->dimension ) {
-			assert(false);
-			genArray( pointerType->get_qualifiers(), pointerType->base, pointerType->dimension, pointerType->get_isVarLen(), pointerType->get_isStatic() );
-		} else {
-			handleQualifiers( pointerType );
-			if ( typeString[ 0 ] == '?' ) {
-				typeString = "* " + typeString;
-			} else {
-				typeString = "*" + typeString;
-			} // if
-			pointerType->base->accept( *visitor );
-		} // if
-	}
-
-	void GenType::postvisit( ArrayType * arrayType ) {
-		genArray( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->get_isVarLen(), arrayType->get_isStatic() );
-	}
-
-	void GenType::postvisit( ReferenceType * refType ) {
-		assert( false );
-		assert( refType->base != 0);
-		handleQualifiers( refType );
-		typeString = "&" + typeString;
-		refType->base->accept( *visitor );
-	}
-
-	void GenType::postvisit( FunctionType * funcType ) {
-		std::ostringstream os;
-
-		if ( typeString != "" ) {
-			if ( typeString[0] == '*' ) {
-				os << "(" << typeString << ")";
-			} else {
-				os << typeString;
-			} // if
-		} // if
-
-		/************* parameters ***************/
-		const std::list<DeclarationWithType *> &pars = funcType->parameters;
-
-		if ( pars.empty() ) {
-			if ( funcType->get_isVarArgs() ) {
-				os << "()";
-			} else {
-				os << "(void)";
-			} // if
-		} else {
-			os << "(" ;
-
-			unsigned int i = 0;
-			for (DeclarationWithType * p : pars) {
-				os << genDemangleType( p->get_type(), "" );
-				if (++i != pars.size()) os << ", ";
-			}
-
-			if ( funcType->get_isVarArgs() ) {
-				os << ", ...";
-			} // if
-			os << ")";
-		} // if
-
-		typeString = os.str();
-
-		if ( funcType->returnVals.size() == 0 ) {
-			typeString += ": void";
-		} else {
-			typeString += ": " + genDemangleType(funcType->returnVals.front()->get_type(), "");
-		} // if
-
-		// add forall
-		if( ! funcType->forall.empty() ) {
-			std::ostringstream os;
-			os << "forall(";
-			unsigned int i = 0;
-			for ( auto td : funcType->forall ) {
-				os << td->typeString() << " " << td->name;
-				if (! td->assertions.empty()) {
-					os << " | { ";
-					unsigned int j = 0;
-					for (DeclarationWithType * assert : td->assertions) {
-						os << genDemangleType(assert->get_type(), assert->name);
-						if (++j != td->assertions.size()) os << ", ";
-					}
-					os << "}";
-				}
-				if (++i != funcType->forall.size()) os << ", ";
-			}
-			os << ")";
-			typeString = typeString + " -> " + os.str();
+
+struct Demangler {
+private:
+	std::string str;
+	size_t index = 0;
+	using Parser = std::function<ast::Type * ( ast::CV::Qualifiers )>;
+	std::vector<std::pair<std::string, Parser>> parsers;
+public:
+	Demangler( const std::string & str );
+
+	bool done() const { return str.size() <= index; }
+	char cur() const { assert( !done() ); return str[index]; }
+	bool expect( char ch ) { return str[index++] == ch; }
+
+	bool isPrefix( const std::string & pref );
+	bool extractNumber( size_t & out );
+	bool extractName( std::string & out );
+	bool stripMangleName( std::string & name );
+
+	ast::Type * parseFunction( ast::CV::Qualifiers tq );
+	ast::Type * parseTuple( ast::CV::Qualifiers tq );
+	ast::Type * parsePointer( ast::CV::Qualifiers tq );
+	ast::Type * parseArray( ast::CV::Qualifiers tq );
+	ast::Type * parseStruct( ast::CV::Qualifiers tq );
+	ast::Type * parseUnion( ast::CV::Qualifiers tq );
+	ast::Type * parseEnum( ast::CV::Qualifiers tq );
+	ast::Type * parseType( ast::CV::Qualifiers tq );
+	ast::Type * parseZero( ast::CV::Qualifiers tq );
+	ast::Type * parseOne( ast::CV::Qualifiers tq );
+
+	ast::Type * parseType();
+	bool parse( std::string & name, ast::Type *& type );
+};
+
+Demangler::Demangler(const std::string & str) : str(str) {
+	for (size_t k = 0; k < ast::BasicType::NUMBER_OF_BASIC_TYPES; ++k) {
+		parsers.emplace_back(Encoding::basicTypes[k], [k]( ast::CV::Qualifiers tq ) {
+			PRINT( std::cerr << "basic type: " << k << std::endl; )
+			return new ast::BasicType( (ast::BasicType::Kind)k, tq );
+		});
+	}
+
+	for (size_t k = 0; k < ast::TypeDecl::NUMBER_OF_KINDS; ++k) {
+		static const std::string typeVariableNames[] = { "DT", "DST", "OT", "FT", "TT", "ALT", };
+		static_assert(
+			sizeof(typeVariableNames)/sizeof(typeVariableNames[0]) == ast::TypeDecl::NUMBER_OF_KINDS,
+			"Each type variable kind should have a demangle name prefix"
+		);
+		parsers.emplace_back(Encoding::typeVariables[k], [k, this]( ast::CV::Qualifiers tq ) -> ast::TypeInstType * {
+			PRINT( std::cerr << "type variable type: " << k << std::endl; )
+			size_t N;
+			if (!extractNumber(N)) return nullptr;
+			return new ast::TypeInstType(
+				toString(typeVariableNames[k], N),
+				(ast::TypeDecl::Kind)k,
+				tq );
+		});
+	}
+
+	parsers.emplace_back(Encoding::void_t, [this]( ast::CV::Qualifiers tq ) { return new ast::VoidType(tq); });
+	parsers.emplace_back(Encoding::function, [this]( ast::CV::Qualifiers tq ) { return parseFunction(tq); });
+	parsers.emplace_back(Encoding::pointer, [this]( ast::CV::Qualifiers tq ) { return parsePointer(tq); });
+	parsers.emplace_back(Encoding::array, [this]( ast::CV::Qualifiers tq ) { return parseArray(tq); });
+	parsers.emplace_back(Encoding::tuple, [this]( ast::CV::Qualifiers tq ) { return parseTuple(tq); });
+	parsers.emplace_back(Encoding::struct_t, [this]( ast::CV::Qualifiers tq ) { return parseStruct(tq); });
+	parsers.emplace_back(Encoding::union_t, [this]( ast::CV::Qualifiers tq ) { return parseUnion(tq); });
+	parsers.emplace_back(Encoding::enum_t, [this]( ast::CV::Qualifiers tq ) { return parseEnum(tq); });
+	parsers.emplace_back(Encoding::type, [this]( ast::CV::Qualifiers tq ) { return parseType(tq); });
+	parsers.emplace_back(Encoding::zero, []( ast::CV::Qualifiers tq ) { return new ast::ZeroType(tq); });
+	parsers.emplace_back(Encoding::one, []( ast::CV::Qualifiers tq ) { return new ast::OneType(tq); });
+}
+
+bool Demangler::extractNumber( size_t & out ) {
+	std::stringstream numss;
+	if ( str.size() <= index ) return false;
+	while ( isdigit( str[index] ) ) {
+		numss << str[index];
+		++index;
+		if ( str.size() == index ) break;
+	}
+	if ( !(numss >> out) ) return false;
+	PRINT( std::cerr << "extractNumber success: " << out << std::endl; )
+	return true;
+}
+
+bool Demangler::extractName( std::string & out ) {
+	size_t len;
+	if ( !extractNumber(len) ) return false;
+	if ( str.size() < index + len ) return false;
+	out = str.substr( index, len );
+	index += len;
+	PRINT( std::cerr << "extractName success: " << out << std::endl; )
+	return true;
+}
+
+bool Demangler::isPrefix( const std::string & pref ) {
+	// Wraps the utility isPrefix function.
+	if ( ::isPrefix( str, pref, index ) ) {
+		index += 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 Demangler::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;
+
+	if (!extractName(name)) return false;
+
+	// Find bounds for type.
+	PRINT( std::cerr << index << " " << str.size() << std::endl; )
+	PRINT( std::cerr << "[");
+	while (isdigit(str.back())) {
+		PRINT(std::cerr << ".");
+		str.pop_back();
+		if (str.size() <= index) return false;
+	}
+	PRINT( std::cerr << "]" << std::endl );
+	if (str.back() != '_') return false;
+	str.pop_back();
+	PRINT( std::cerr << str.size() << " " << name << " " << str.substr(index) << std::endl; )
+	return index < str.size();
+}
+
+ast::Type * Demangler::parseFunction( ast::CV::Qualifiers tq ) {
+	PRINT( std::cerr << "function..." << std::endl; )
+	if ( done() ) return nullptr;
+	ast::FunctionType * ftype = new ast::FunctionType( ast::FixedArgs, tq );
+	std::unique_ptr<ast::Type> manager( ftype );
+	ast::Type * retVal = parseType();
+	if ( !retVal ) return nullptr;
+	PRINT( std::cerr << "with return type: " << retVal << std::endl; )
+	ftype->returns.emplace_back( retVal );
+	if ( done() || !expect('_') ) return nullptr;
+	while ( !done() ) {
+		PRINT( std::cerr << "got ch: " << cur() << std::endl; )
+		if ( cur() == '_' ) return manager.release();
+		ast::Type * param = parseType();
+		if ( !param ) return nullptr;
+		PRINT( std::cerr << "with parameter : " << param << std::endl; )
+		ftype->params.emplace_back( param );
+	}
+	return nullptr;
+}
+
+ast::Type * Demangler::parseTuple( ast::CV::Qualifiers tq ) {
+	PRINT( std::cerr << "tuple..." << std::endl; )
+	std::vector<ast::ptr<ast::Type>> types;
+	size_t ncomponents;
+	if ( !extractNumber(ncomponents) ) return nullptr;
+	for ( size_t i = 0; i < ncomponents; ++i ) {
+		if ( done() ) return nullptr;
+		PRINT( std::cerr << "got ch: " << cur() << std::endl; )
+		ast::Type * t = parseType();
+		if ( !t ) return nullptr;
+		PRINT( std::cerr << "with type : " << t << std::endl; )
+		types.push_back( t );
+	}
+	return new ast::TupleType( std::move( types ), tq );
+}
+
+ast::Type * Demangler::parsePointer( ast::CV::Qualifiers tq ) {
+	PRINT( std::cerr << "pointer..." << std::endl; )
+	ast::Type * t = parseType();
+	if ( !t ) return nullptr;
+	return new ast::PointerType( t, tq );
+}
+
+ast::Type * Demangler::parseArray( ast::CV::Qualifiers tq ) {
+	PRINT( std::cerr << "array..." << std::endl; )
+	size_t length;
+	if ( !extractNumber(length) ) return nullptr;
+	ast::Type * t = parseType();
+	if ( !t ) return nullptr;
+	return new ast::ArrayType(
+		t,
+		ast::ConstantExpr::from_ulong( CodeLocation(), length ),
+		ast::FixedLen,
+		ast::DynamicDim,
+		tq );
+}
+
+ast::Type * Demangler::parseStruct( ast::CV::Qualifiers tq ) {
+	PRINT( std::cerr << "struct..." << std::endl; )
+	std::string name;
+	if ( !extractName(name) ) return nullptr;
+	return new ast::StructInstType( name, tq );
+}
+
+ast::Type * Demangler::parseUnion( ast::CV::Qualifiers tq ) {
+	PRINT( std::cerr << "union..." << std::endl; )
+	std::string name;
+	if ( !extractName(name) ) return nullptr;
+	return new ast::UnionInstType( name, tq );
+}
+
+ast::Type * Demangler::parseEnum( ast::CV::Qualifiers tq ) {
+	PRINT( std::cerr << "enum..." << std::endl; )
+	std::string name;
+	if ( !extractName(name) ) return nullptr;
+	return new ast::EnumInstType( name, tq );
+}
+
+ast::Type * Demangler::parseType( ast::CV::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 ast::TypeInstType( name, ast::TypeDecl::Dtype, tq );
+}
+
+ast::Type * Demangler::parseType() {
+	if (done()) return nullptr;
+
+	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;
 		}
-	}
-
-	std::string GenType::handleGeneric( ReferenceToType * refType ) {
-		if ( ! refType->parameters.empty() ) {
-			std::ostringstream os;
-			// TODO: ???
-			// PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
-			os << "(";
-			// cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() );
-			os << ") ";
-			return os.str();
-		}
-		return "";
-	}
-
-	void GenType::postvisit( StructInstType * structInst )  {
-		typeString = "struct " + structInst->name + handleGeneric( structInst ) + " " + typeString;
-		handleQualifiers( structInst );
-	}
-
-	void GenType::postvisit( UnionInstType * unionInst ) {
-		typeString = "union " + unionInst->name + handleGeneric( unionInst ) + " " + typeString;
-		handleQualifiers( unionInst );
-	}
-
-	void GenType::postvisit( EnumInstType * enumInst ) {
-		typeString = "enum " + enumInst->name + " " + typeString;
-		handleQualifiers( enumInst );
-	}
-
-	void GenType::postvisit( TypeInstType * typeInst ) {
-		typeString = typeInst->name + " " + typeString;
-		handleQualifiers( typeInst );
-	}
-
-	void GenType::postvisit( TupleType * tupleType ) {
-		unsigned int i = 0;
-		std::ostringstream os;
-		os << "[";
-		for ( Type * t : *tupleType ) {
-			i++;
-			os << genDemangleType( t, "" ) << (i == tupleType->size() ? "" : ", ");
-		}
-		os << "] ";
-		typeString = os.str() + typeString;
-	}
-
-	void GenType::postvisit( VarArgsType * varArgsType ) {
-		typeString = "__builtin_va_list " + typeString;
-		handleQualifiers( varArgsType );
-	}
-
-	void GenType::postvisit( ZeroType * zeroType ) {
-		// ideally these wouldn't hit codegen at all, but should be safe to make them ints
-		typeString = "zero_t " + typeString;
-		handleQualifiers( zeroType );
-	}
-
-	void GenType::postvisit( OneType * oneType ) {
-		// ideally these wouldn't hit codegen at all, but should be safe to make them ints
-		typeString = "one_t " + typeString;
-		handleQualifiers( oneType );
-	}
-
-	void GenType::postvisit( GlobalScopeType * globalType ) {
-		handleQualifiers( globalType );
-	}
-
-	void GenType::postvisit( QualifiedType * qualType ) {
-		std::ostringstream os;
-		os << genDemangleType( qualType->parent, "" ) << "." << genDemangleType( qualType->child, "" ) << typeString;
-		typeString = os.str();
-		handleQualifiers( qualType );
-	}
-
-	void GenType::handleQualifiers( Type * type ) {
-		if ( type->get_const() ) {
-			typeString = "const " + typeString;
-		} // if
-		if ( type->get_volatile() ) {
-			typeString = "volatile " + typeString;
-		} // if
-		if ( type->get_restrict() ) {
-			typeString = "__restrict " + typeString;
-		} // if
-		if ( type->get_atomic() ) {
-			typeString = "_Atomic " + typeString;
-		} // if
-	}
-}
-
-
-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 genDemangleType(type, name);
-			}
-		} // namespace
-	} // namespace Mangler
-} // namespace SymTab
+		if ( !expect('_') ) return nullptr;
+	}
+
+	ast::CV::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 then apply 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(), index);
+	ast::Type * ret = iter->second(tq);
+	if ( !ret ) return nullptr;
+	return ret;
+}
+
+bool Demangler::parse( std::string & name, ast::Type *& type) {
+	if ( !stripMangleName(name) ) return false;
+	PRINT( std::cerr << "stripped name: " << name << std::endl; )
+	ast::Type * t = parseType();
+	if ( !t ) return false;
+	type = t;
+	return true;
+}
+
+std::string demangle( const std::string & mangleName ) {
+	using namespace CodeGen;
+	Demangler demangler( mangleName );
+	std::string name;
+	ast::Type * type = nullptr;
+	if ( !demangler.parse( name, type ) ) return mangleName;
+	ast::readonly<ast::Type> roType = type;
+	if ( auto info = operatorLookupByOutput( name ) ) name = info->inputName;
+	return genType( type, name, Options( false, false, false, false ) );
+}
+
+} // namespace
+
+} // namespace Mangle
 
 extern "C" {
 	char * cforall_demangle(const char * mangleName, int option __attribute__((unused))) {
-		const std::string & demangleName = SymTab::Mangler::demangle(mangleName);
+		const std::string & demangleName = Mangle::demangle(mangleName);
 		return strdup(demangleName.c_str());
 	}
Index: src/SymTab/FixFunction.cc
===================================================================
--- src/SymTab/FixFunction.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/SymTab/FixFunction.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -22,86 +22,9 @@
 #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 {
-	struct FixFunction_new final : public ast::WithShortCircuiting {
+	struct FixFunction final : public ast::WithShortCircuiting {
 		bool isVoid = false;
 
@@ -147,5 +70,5 @@
 
 const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid ) {
-	ast::Pass< FixFunction_new > fixer;
+	ast::Pass< FixFunction > fixer;
 	dwt = dwt->accept( fixer );
 	isVoid |= fixer.core.isVoid;
@@ -154,5 +77,5 @@
 
 const ast::Type * fixFunction( const ast::Type * type, bool & isVoid ) {
-	ast::Pass< FixFunction_new > fixer;
+	ast::Pass< FixFunction > fixer;
 	type = type->accept( fixer );
 	isVoid |= fixer.core.isVoid;
Index: src/SymTab/FixFunction.h
===================================================================
--- src/SymTab/FixFunction.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/SymTab/FixFunction.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -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/GenImplicitCall.cpp
===================================================================
--- src/SymTab/GenImplicitCall.cpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/SymTab/GenImplicitCall.cpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -32,5 +32,5 @@
 template< typename OutIter >
 ast::ptr< ast::Stmt > genCall(
-	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
 	const CodeLocation & loc, const std::string & fname, OutIter && out,
 	const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
@@ -42,5 +42,5 @@
 template< typename OutIter >
 ast::ptr< ast::Stmt > genScalarCall(
-	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
 	const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
 	const ast::Type * addCast = nullptr
@@ -98,5 +98,5 @@
 template< typename OutIter >
 void genArrayCall(
-	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
 	const CodeLocation & loc, const std::string & fname, OutIter && out,
 	const ast::ArrayType * array, const ast::Type * addCast = nullptr,
@@ -167,5 +167,5 @@
 template< typename OutIter >
 ast::ptr< ast::Stmt > genCall(
-	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
 	const CodeLocation & loc, const std::string & fname, OutIter && out,
 	const ast::Type * type, const ast::Type * addCast, LoopDirection forward
@@ -185,5 +185,5 @@
 
 ast::ptr< ast::Stmt > genImplicitCall(
-	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
 	const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
 	LoopDirection forward
Index: src/SymTab/GenImplicitCall.hpp
===================================================================
--- src/SymTab/GenImplicitCall.hpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/SymTab/GenImplicitCall.hpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -26,5 +26,5 @@
 /// dstParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
 ast::ptr<ast::Stmt> genImplicitCall(
-	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
 	const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
 	LoopDirection forward = LoopForward
Index: c/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(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: c/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(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 df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/SymTab/Mangler.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -24,373 +24,13 @@
 #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 {
 	namespace {
 		/// Mangles names to a unique C identifier
-		struct Mangler_new : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler_new>, public ast::WithGuards {
-			Mangler_new( Mangle::Mode mode );
-			Mangler_new( const Mangler_new & ) = delete;
+		struct Mangler : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler>, public ast::WithGuards {
+			Mangler( Mangle::Mode mode );
+			Mangler( const Mangler & ) = delete;
 
 			void previsit( const ast::Node * ) { visit_children = false; }
@@ -432,7 +72,7 @@
 
 		  private:
-			Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
+			Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
 				int nextVarNum, const VarMapType& varNums );
-			friend class ast::Pass<Mangler_new>;
+			friend class ast::Pass<Mangler>;
 
 		  private:
@@ -441,13 +81,13 @@
 
 			void printQualifiers( const ast::Type *type );
-		}; // Mangler_new
+		}; // Mangler
 	} // namespace
 
 	std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
-		return ast::Pass<Mangler_new>::read( decl, mode );
+		return ast::Pass<Mangler>::read( decl, mode );
 	}
 
 	namespace {
-		Mangler_new::Mangler_new( Mangle::Mode mode )
+		Mangler::Mangler( Mangle::Mode mode )
 			: nextVarNum( 0 ), isTopLevel( true ),
 			mangleOverridable  ( ! mode.no_overrideable   ),
@@ -455,5 +95,5 @@
 			mangleGenericParams( ! mode.no_generic_params ) {}
 
-		Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
+		Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
 			int nextVarNum, const VarMapType& varNums )
 			: varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
@@ -461,5 +101,5 @@
 			mangleGenericParams( mangleGenericParams ) {}
 
-		void Mangler_new::mangleDecl( const ast::DeclWithType * decl ) {
+		void Mangler::mangleDecl( const ast::DeclWithType * decl ) {
 			bool wasTopLevel = isTopLevel;
 			if ( isTopLevel ) {
@@ -491,18 +131,18 @@
 		}
 
-		void Mangler_new::postvisit( const ast::ObjectDecl * decl ) {
+		void Mangler::postvisit( const ast::ObjectDecl * decl ) {
 			mangleDecl( decl );
 		}
 
-		void Mangler_new::postvisit( const ast::FunctionDecl * decl ) {
+		void Mangler::postvisit( const ast::FunctionDecl * decl ) {
 			mangleDecl( decl );
 		}
 
-		void Mangler_new::postvisit( const ast::VoidType * voidType ) {
+		void Mangler::postvisit( const ast::VoidType * voidType ) {
 			printQualifiers( voidType );
 			mangleName += Encoding::void_t;
 		}
 
-		void Mangler_new::postvisit( const ast::BasicType * basicType ) {
+		void Mangler::postvisit( const ast::BasicType * basicType ) {
 			printQualifiers( basicType );
 			assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
@@ -510,5 +150,5 @@
 		}
 
-		void Mangler_new::postvisit( const ast::PointerType * pointerType ) {
+		void Mangler::postvisit( const ast::PointerType * pointerType ) {
 			printQualifiers( pointerType );
 			// mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
@@ -517,5 +157,5 @@
 		}
 
-		void Mangler_new::postvisit( const ast::ArrayType * arrayType ) {
+		void Mangler::postvisit( const ast::ArrayType * arrayType ) {
 			// TODO: encode dimension
 			printQualifiers( arrayType );
@@ -524,5 +164,5 @@
 		}
 
-		void Mangler_new::postvisit( const ast::ReferenceType * refType ) {
+		void Mangler::postvisit( const ast::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.),
@@ -534,5 +174,5 @@
 		}
 
-		void Mangler_new::postvisit( const ast::FunctionType * functionType ) {
+		void Mangler::postvisit( const ast::FunctionType * functionType ) {
 			printQualifiers( functionType );
 			mangleName += Encoding::function;
@@ -549,5 +189,5 @@
 		}
 
-		void Mangler_new::mangleRef(
+		void Mangler::mangleRef(
 				const ast::BaseInstType * refType, const std::string & prefix ) {
 			printQualifiers( refType );
@@ -566,17 +206,17 @@
 		}
 
-		void Mangler_new::postvisit( const ast::StructInstType * aggregateUseType ) {
+		void Mangler::postvisit( const ast::StructInstType * aggregateUseType ) {
 			mangleRef( aggregateUseType, Encoding::struct_t );
 		}
 
-		void Mangler_new::postvisit( const ast::UnionInstType * aggregateUseType ) {
+		void Mangler::postvisit( const ast::UnionInstType * aggregateUseType ) {
 			mangleRef( aggregateUseType, Encoding::union_t );
 		}
 
-		void Mangler_new::postvisit( const ast::EnumInstType * aggregateUseType ) {
+		void Mangler::postvisit( const ast::EnumInstType * aggregateUseType ) {
 			mangleRef( aggregateUseType, Encoding::enum_t );
 		}
 
-		void Mangler_new::postvisit( const ast::TypeInstType * typeInst ) {
+		void Mangler::postvisit( const ast::TypeInstType * typeInst ) {
 			VarMapType::iterator varNum = varNums.find( typeInst->name );
 			if ( varNum == varNums.end() ) {
@@ -594,10 +234,10 @@
 		}
 
-		void Mangler_new::postvisit( const ast::TraitInstType * inst ) {
+		void Mangler::postvisit( const ast::TraitInstType * inst ) {
 			printQualifiers( inst );
 			mangleName += std::to_string( inst->name.size() ) + inst->name;
 		}
 
-		void Mangler_new::postvisit( const ast::TupleType * tupleType ) {
+		void Mangler::postvisit( const ast::TupleType * tupleType ) {
 			printQualifiers( tupleType );
 			mangleName += Encoding::tuple + std::to_string( tupleType->types.size() );
@@ -605,5 +245,5 @@
 		}
 
-		void Mangler_new::postvisit( const ast::VarArgsType * varArgsType ) {
+		void Mangler::postvisit( const ast::VarArgsType * varArgsType ) {
 			printQualifiers( varArgsType );
 			static const std::string vargs = "__builtin_va_list";
@@ -611,13 +251,13 @@
 		}
 
-		void Mangler_new::postvisit( const ast::ZeroType * ) {
+		void Mangler::postvisit( const ast::ZeroType * ) {
 			mangleName += Encoding::zero;
 		}
 
-		void Mangler_new::postvisit( const ast::OneType * ) {
+		void Mangler::postvisit( const ast::OneType * ) {
 			mangleName += Encoding::one;
 		}
 
-		void Mangler_new::postvisit( const ast::QualifiedType * qualType ) {
+		void Mangler::postvisit( const ast::QualifiedType * qualType ) {
 			bool inqual = inQualifiedType;
 			if ( !inqual ) {
@@ -635,5 +275,5 @@
 		}
 
-		void Mangler_new::postvisit( const ast::TypeDecl * decl ) {
+		void Mangler::postvisit( const ast::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.
@@ -641,5 +281,5 @@
 			// 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_new should not visit typedecl: %s", toCString(decl));
+			assertf(false, "Mangler should not visit typedecl: %s", toCString(decl));
 			assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
 			mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
@@ -653,5 +293,5 @@
 		}
 
-		void Mangler_new::printQualifiers( const ast::Type * type ) {
+		void Mangler::printQualifiers( const ast::Type * type ) {
 			// skip if not including qualifiers
 			if ( typeMode ) return;
@@ -678,5 +318,5 @@
 				} // for
 				for ( auto & assert : funcType->assertions ) {
-					assertionNames.push_back( ast::Pass<Mangler_new>::read(
+					assertionNames.push_back( ast::Pass<Mangler>::read(
 						assert->var.get(),
 						mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) );
Index: src/SymTab/Mangler.h
===================================================================
--- src/SymTab/Mangler.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/SymTab/Mangler.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -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: c/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(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: c/SymTab/Validate.h
===================================================================
--- src/SymTab/Validate.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(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: c/SymTab/ValidateType.cc
===================================================================
--- src/SymTab/ValidateType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(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: c/SymTab/ValidateType.h
===================================================================
--- src/SymTab/ValidateType.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(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 df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/SymTab/module.mk	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -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) \
Index: c/SynTree/AddressExpr.cc
===================================================================
--- src/SynTree/AddressExpr.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,89 +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.
-//
-// AddressExpr.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 23:54:44 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Feb 28 13:13:38 2019
-// Update Count     : 10
-//
-
-#include <ostream>           // for ostream, operator<<, basic_ostream, endl
-#include <string>            // for operator<<, string
-
-#include "Common/utility.h"  // for maybeClone
-#include "Expression.h"      // for AddressExpr, Expression
-#include "Type.h"            // for PointerType, Type, Type::Qualifiers
-
-// Address expressions are typed based on the following inference rules:
-//    E : lvalue T  &..& (n references)
-//   &E :        T *&..& (n references)
-//
-//    E : T  &..&        (m references)
-//   &E : T *&..&        (m-1 references)
-//
-// That is, lvalues becomes
-
-namespace {
-	Type * addrType( Type * type ) {
-		if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
-			return new ReferenceType( refType->get_qualifiers(), addrType( refType->base ) );
-		} else {
-			return new PointerType( Type::Qualifiers(), type->clone() );
-		}
-	}
-}
-
-AddressExpr::AddressExpr( Expression *arg ) : Expression(), arg( arg ) {
-	if ( arg->result ) {
-		if ( arg->get_lvalue() ) {
-			// lvalue, retains all layers of reference and gains a pointer inside the references
-			set_result( addrType( arg->result ) );
-		} else {
-			// taking address of non-lvalue -- must be a reference, loses one layer of reference
-			if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( arg->result ) ) {
-				set_result( addrType( refType->base ) );
-			} else {
-				if(!arg->result->location.isSet()) arg->result->location = arg->location;
-				SemanticError( arg->result, "Attempt to take address of non-lvalue expression: " );
-			} // if
-		}
-	}
-}
-
-AddressExpr::AddressExpr( const AddressExpr &other ) : Expression( other ), arg( maybeClone( other.arg ) ) {
-}
-
-AddressExpr::~AddressExpr() {
-	delete arg;
-}
-
-void AddressExpr::print( std::ostream &os, Indenter indent ) const {
-	os << "Address of:" << std::endl;
-	if ( arg ) {
-		os << indent+1;
-		arg->print( os, indent+1 );
-	} // if
-}
-
-LabelAddressExpr::LabelAddressExpr( const Label &arg ) : arg( arg ) {
-	// label address always has type void *
-	result = new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) );
-}
-LabelAddressExpr::LabelAddressExpr( const LabelAddressExpr & other ) : Expression( other ), arg( other.arg ) {}
-LabelAddressExpr::~LabelAddressExpr() {}
-
-void LabelAddressExpr::print( std::ostream & os, Indenter ) const {
-	os << "Address of label:" << arg;
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/AggregateDecl.cc
===================================================================
--- src/SynTree/AggregateDecl.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,147 +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.
-//
-// AggregateDecl.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 23:56:39 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul  1 09:12:33 2022
-// Update Count     : 32
-//
-
-#include <list>                  // for list
-#include <ostream>               // for operator<<, basic_ostream, ostream
-#include <string>                // for operator<<, string, char_traits
-
-#include "Attribute.h"           // for Attribute
-#include "Common/Eval.h"         // for eval
-#include "Common/utility.h"      // for printAll, cloneAll, deleteAll
-#include "Declaration.h"         // for AggregateDecl, TypeDecl, Declaration
-#include "Expression.h"
-#include "Initializer.h"
-#include "LinkageSpec.h"         // for Spec, linkageName, Cforall
-#include "Type.h"                // for Type, Type::StorageClasses
-
-
-// These must harmonize with the corresponding AggregateDecl::Aggregate enumerations.
-static const char * aggregateNames[] = { "struct", "union", "enum", "exception", "trait", "generator", "coroutine", "monitor", "thread", "NoAggregateName" };
-
-const char * AggregateDecl::aggrString( AggregateDecl::Aggregate aggr ) {
-	return aggregateNames[aggr];
-}
-
-AggregateDecl::AggregateDecl( const std::string &name, const std::list< Attribute * > & attributes, LinkageSpec::Spec linkage ) : Parent( name, Type::StorageClasses(), linkage ), body( false ), attributes( attributes ) {
-}
-
-AggregateDecl::AggregateDecl( const AggregateDecl &other ) : Parent( other ) {
-	cloneAll( other.members, members );
-	cloneAll( other.parameters, parameters );
-	cloneAll( other.attributes, attributes );
-	body = other.body;
-}
-
-AggregateDecl::~AggregateDecl() {
-	deleteAll( attributes );
-	deleteAll( parameters );
-	deleteAll( members );
-}
-
-void AggregateDecl::print( std::ostream &os, Indenter indent ) const {
-	using std::string;
-	using std::endl;
-
-	os << typeString() << " " << name << ":";
-	if ( get_linkage() != LinkageSpec::Cforall ) {
-		os << " " << LinkageSpec::name( linkage );
-	} // if
-	os << " with body " << has_body();
-	if ( ! parameters.empty() ) {
-		os << endl << indent << "... with parameters" << endl;
-		printAll( parameters, os, indent+1 );
-	} // if
-	if ( ! members.empty() ) {
-		os << endl << indent << "... with members" << endl;
-		printAll( members, os, indent+1 );
-	} // if
-	if ( ! attributes.empty() ) {
-		os << endl << indent << "... with attributes" << endl;
-		printAll( attributes, os, indent+1 );
-	} // if
-	os << endl;
-}
-
-void AggregateDecl::printShort( std::ostream &os, Indenter indent ) const {
-	using std::string;
-	using std::endl;
-
-	os << typeString() << " " << name << " with body " << has_body() << endl;
-
-	if ( ! parameters.empty() ) {
-		os << indent << "... with parameters" << endl;
-		printAll( parameters, os, indent+1 );
-	} // if
-}
-
-const char * StructDecl::typeString() const { return aggrString( kind ); }
-
-StructInstType * StructDecl::makeInst( std::list< Expression * > const & new_parameters ) {
-	std::list< Expression * > copy_parameters;
-	cloneAll( new_parameters, copy_parameters );
-	return makeInst( copy( copy_parameters ) );
-}
-
-StructInstType * StructDecl::makeInst( std::list< Expression * > && new_parameters ) {
-	assert( parameters.size() == new_parameters.size() );
-	StructInstType * type = new StructInstType( noQualifiers, this );
-	type->parameters = std::move( new_parameters );
-	return type;
-}
-
-const char * UnionDecl::typeString() const { return aggrString( Union ); }
-
-const char * EnumDecl::typeString() const { return aggrString( Enum ); }
-
-void EnumDecl::print( std::ostream & os, Indenter indent ) const {
-	AggregateDecl::print(os, indent);
-	os << " with base? " << (base? "True" : "False") << std::endl;
-	if ( base ) {
-		os << "Base Type of Enum:" << std::endl;
-		base->print(os, indent);
-	}
-	os <<  std::endl << "End of EnumDecl::print" << std::endl;
-}
-
-const char * TraitDecl::typeString() const { return aggrString( Trait ); }
-
-bool EnumDecl::valueOf( Declaration * enumerator, long long int & value ) {
-	if ( enumValues.empty() ) {
-		long long int currentValue = 0;
-		for ( Declaration * member : members ) {
-			ObjectDecl * field = strict_dynamic_cast< ObjectDecl * >( member );
-			if ( field->init ) {
-				SingleInit * init = strict_dynamic_cast< SingleInit * >( field->init );
-				auto result = eval( init->value );
-				if ( ! result.second ) SemanticError( init->location, toString( "Enumerator value for '", field, "' is not an integer constant" ) );
-				currentValue = result.first;
-			}
-			assertf( enumValues.count( field->name ) == 0, "Enum %s has multiple members with the name %s", name.c_str(), field->name.c_str() );
-			enumValues[ field->name ] = currentValue;
-			++currentValue;
-		}
-	}
-	if ( enumValues.count( enumerator->name ) ) {
-		value = enumValues[ enumerator->name ];
-		return true;
-	}
-	return false;
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/ApplicationExpr.cc
===================================================================
--- src/SynTree/ApplicationExpr.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,103 +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.
-//
-// ApplicationExpr.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Aug 12 14:28:00 2019
-// Update Count     : 5
-//
-
-#include <cassert>               // for strict_dynamic_cast, assert
-#include <list>                  // for list
-#include <map>                   // for _Rb_tree_const_iterator, map, map<>:...
-#include <memory>                // for unique_ptr
-#include <ostream>               // for operator<<, ostream, basic_ostream
-#include <string>                // for operator<<, string, char_traits
-#include <utility>               // for pair
-
-#include "Common/utility.h"      // for maybeClone, cloneAll, deleteAll, pri...
-#include "Declaration.h"         // for Declaration
-#include "Expression.h"          // for ParamEntry, ApplicationExpr, Expression
-#include "InitTweak/InitTweak.h" // for getFunction
-#include "ResolvExpr/Unify.h"    // for extractResultType
-#include "Type.h"                // for Type, PointerType, FunctionType
-
-ParamEntry::ParamEntry( UniqueId decl, Declaration * declptr, Type * actualType, Type * formalType, Expression* expr )
-		: decl( decl ), declptr( declptr ), actualType( actualType ), formalType( formalType ), expr( expr ) {
-	}
-
-ParamEntry::ParamEntry( const ParamEntry &other ) :
-		decl( other.decl ), declptr( other.declptr ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) ) {
-}
-
-ParamEntry::~ParamEntry() {
-	// delete declptr;
-	delete actualType;
-	delete formalType;
-	delete expr;
-}
-
-ParamEntry::ParamEntry( ParamEntry && other ) :
-		decl( other.decl ), declptr( other.declptr ), actualType( other.actualType ), formalType( other.formalType ), expr( other.expr ) {
-	new (&other) ParamEntry();
-}
-
-ParamEntry & ParamEntry::operator=( ParamEntry && other ) {
-	if ( &other == this ) return *this;
-	this->~ParamEntry();
-	new (this) ParamEntry(other.decl, other.declptr, other.actualType, other.formalType, other.expr);
-	new (&other) ParamEntry();
-
-	return *this;
-}
-
-ApplicationExpr::ApplicationExpr( Expression *funcExpr, const std::list<Expression *> & args ) : function( funcExpr ), args( args ) {
-	PointerType *pointer = strict_dynamic_cast< PointerType* >( funcExpr->get_result() );
-	FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() );
-
-	set_result( ResolvExpr::extractResultType( function ) );
-
-	assert( result );
-}
-
-ApplicationExpr::ApplicationExpr( const ApplicationExpr &other ) :
-		Expression( other ), function( maybeClone( other.function ) ) {
-	cloneAll( other.args, args );
-}
-
-ApplicationExpr::~ApplicationExpr() {
-	delete function;
-	deleteAll( args );
-}
-
-bool ApplicationExpr::get_lvalue() const {
-	// from src/GenPoly/Lvalue.cc: isIntrinsicReference
-	static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
-	if ( const DeclarationWithType * func = InitTweak::getFunction( this ) ) {
-		return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name);
-	}
-	return false;
-}
-
-void ApplicationExpr::print( std::ostream &os, Indenter indent ) const {
-	os << "Application of" << std::endl << indent+1;
-	function->print( os, indent+1 );
-	os << std::endl;
-	if ( ! args.empty() ) {
-		os << indent << "... to arguments" << std::endl;
-		printAll( args, os, indent+1 );
-	} // if
-	Expression::print( os, indent );
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/ArrayType.cc
===================================================================
--- src/SynTree/ArrayType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,65 +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.
-//
-// ArrayType.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 17 09:40:30 2017
-// Update Count     : 13
-//
-
-#include <list>              // for list
-#include <ostream>           // for operator<<, ostream
-
-#include "Common/utility.h"  // for maybeClone
-#include "Expression.h"      // for Expression
-#include "Type.h"            // for ArrayType, Type, Type::Qualifiers
-
-class Attribute;
-
-
-ArrayType::ArrayType( const Type::Qualifiers &tq, Type *base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes )
-	: Type( tq, attributes ), base( base ), dimension( dimension ), isVarLen( isVarLen ), isStatic( isStatic ) {
-}
-
-ArrayType::ArrayType( const ArrayType &other )
-		: Type( other ), base( maybeClone( other.base ) ), dimension( maybeClone( other.dimension ) ),
-		  isVarLen( other.isVarLen ), isStatic( other.isStatic ) {
-}
-
-ArrayType::~ArrayType() {
-	delete base;
-	delete dimension;
-}
-
-void ArrayType::print( std::ostream &os, Indenter indent ) const {
-	Type::print( os, indent );
-	if ( isStatic ) {
-		os << "static ";
-	} // if
-	if ( isVarLen ) {
-		os << "variable length array of ";
-	} else if ( dimension ) {
-		os << "array of ";
-	} else {
-		os << "open array of ";
-	} // if
-	if ( base ) {
-		base->print( os, indent );
-	} // if
-	if ( dimension ) {
-		os << " with dimension of ";
-		dimension->print( os, indent );
-	} // if
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/AttrType.cc
===================================================================
--- src/SynTree/AttrType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,61 +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.
-//
-// AttrType.cc.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  1 17:17:59 2017
-// Update Count     : 3
-//
-
-#include <list>              // for list
-#include <ostream>           // for operator<<, ostream, basic_ostream
-#include <string>            // for char_traits, operator<<, string
-
-#include "Common/utility.h"  // for maybeClone
-#include "Expression.h"      // for Expression
-#include "Type.h"            // for AttrType, Type, Type::Qualifiers
-
-class Attribute;
-
-
-AttrType::AttrType( const Type::Qualifiers &tq, const std::string &name, Expression *expr, const std::list< Attribute * > & attributes )
-	: Type( tq, attributes ), name( name ), expr( expr ), type( 0 ), isType( false ) {
-}
-
-AttrType::AttrType( const Type::Qualifiers &tq, const std::string &name, Type *type, const std::list< Attribute * > & attributes )
-	: Type( tq, attributes ), name( name ), expr( 0 ), type( type ), isType( true ) {
-}
-
-AttrType::AttrType( const AttrType &other )
-	: Type( other ), name( other.name ), expr( maybeClone( other.expr ) ), type( maybeClone( other.type ) ), isType( other.isType ) {
-}
-
-AttrType::~AttrType() {
-	delete expr;
-	delete type;
-}
-
-void AttrType::print( std::ostream &os, Indenter indent ) const {
-	Type::print( os, indent );
-	os << "attribute " << name << " applied to ";
-	if ( expr ) {
-		os << "expression ";
-		expr->print( os, indent );
-	} // if
-	if ( type ) {
-		os << "type ";
-		type->print( os, indent );
-	} // if
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Attribute.cc
===================================================================
--- src/SynTree/Attribute.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,69 +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.
-//
-// Attribute.cc --
-//
-// Author           : Rob Schluntz
-// Created On       : Mon June 06 14:51:16 2016
-// Last Modified By : Rob Schluntz
-// Last Modified On : Mon June 06 14:54:48 2016
-// Update Count     : 1
-//
-
-#include <ostream>           // for operator<<, ostream, basic_ostream, endl
-#include <set>
-
-#include "Attribute.h"
-#include "Common/utility.h"  // for cloneAll, deleteAll, printAll
-#include "Expression.h"      // for Expression
-
-Attribute::Attribute( const Attribute &other ) : BaseSyntaxNode( other ), name( other.name ) {
-	cloneAll( other.parameters, parameters );
-}
-
-Attribute::~Attribute() {
-	deleteAll( parameters );
-}
-
-bool Attribute::isValidOnFuncParam() const {
-	// attributes such as aligned, cleanup, etc. produce GCC errors when they appear
-	// on function parameters. Maintain here a whitelist of attribute names that are
-	// allowed to appear on parameters.
-	static std::set< std::string > valid = {
-		"noreturn", "unused"
-	};
-	return valid.count( normalizedName() );
-}
-
-std::string Attribute::normalizedName() const {
-	// trim beginning/ending _, convert to lowercase
-	auto begin = name.find_first_not_of('_');
-	auto end = name.find_last_not_of('_');
-	if (begin == std::string::npos || end == std::string::npos) return "";
-	std::string ret;
-	ret.reserve( end-begin+1 );
-	std::transform( &name[begin], &name[end+1], back_inserter( ret ), tolower );
-	return ret;
-}
-
-void Attribute::print( std::ostream &os, Indenter indent ) const {
-	using std::endl;
-	using std::string;
-
-	if ( ! empty() ) {
-		os << "Attribute with name: " << name;
-		if ( ! parameters.empty() ) {
-			os << " with parameters: " << endl;
-			printAll( parameters, os, indent+1 );
-		}
-	}
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Attribute.h
===================================================================
--- src/SynTree/Attribute.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,63 +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.
-//
-// Declaration.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Feb 13 21:34:08 2020
-// Update Count     : 40
-//
-
-#pragma once
-
-#include <iosfwd>  // for ostream
-#include <list>    // for list
-#include <string>  // for string, operator==
-
-#include "BaseSyntaxNode.h"
-#include "Mutator.h"
-#include "Visitor.h"
-
-class Expression;
-
-// GCC attribute
-// https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Attribute-Syntax.html#Attribute-Syntax
-class Attribute : public BaseSyntaxNode {
-  public:
-	std::string name;
-	// to keep things nice and tight, use NameExpr for special identifier parameters
-	std::list< Expression * > parameters;
-
-	Attribute( std::string name = "", const std::list< Expression * > & parameters = std::list< Expression * >() ) : name( name ), parameters( parameters ) {}
-	Attribute( const Attribute &other );
-	virtual ~Attribute();
-
-	const std::string & get_name() const { return name; }
-	void set_name( const std::string & newValue ) { name = newValue; }
-	std::list< Expression * > & get_parameters() { return parameters; }
-	bool empty() const { return name == ""; }
-
-	std::string normalizedName() const;
-
-	/// true if this attribute is allowed to appear attached to a function parameter
-	bool isValidOnFuncParam() const;
-
-	Attribute * clone() const override { return new Attribute( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Attribute * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-const std::list< Attribute * > noAttributes;
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/BaseSyntaxNode.cc
===================================================================
--- src/SynTree/BaseSyntaxNode.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,31 +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.
-//
-// BaseSyntaxNode.cc --
-//
-// Author           : Andrew Beach
-// Created On       : Fri May 13 13:58:00 2022
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri May 13 14:01:00 2022
-// Update Count     : 0
-//
-
-#include "BaseSyntaxNode.h"
-
-std::ostream & operator<<( std::ostream & out, const BaseSyntaxNode * node ) {
-    if ( node ) {
-        node->print( out );
-    } else {
-        out << "nullptr";
-    }
-    return out;
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/BaseSyntaxNode.h
===================================================================
--- src/SynTree/BaseSyntaxNode.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,53 +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.
-//
-// BaseSyntaxNode.h --
-//
-// Author           : Thierry Delisle
-// Created On       : Tue Feb 14 07:44:20 2017
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Jul 10 16:13:49 2019
-// Update Count     : 4
-//
-
-#pragma once
-
-#include "Common/CodeLocation.h"
-#include "Common/Indenter.h"
-#include "Common/Stats.h"
-
-class Visitor;
-class Mutator;
-
-class BaseSyntaxNode {
-  public:
-	static Stats::Counters::SimpleCounter* new_nodes;
-
-	CodeLocation location;
-
-	BaseSyntaxNode() { ++*new_nodes; }
-	BaseSyntaxNode( const BaseSyntaxNode & o ) : location(o.location) { ++*new_nodes; }
-	BaseSyntaxNode & operator=( const BaseSyntaxNode & ) = default;
-
-	virtual ~BaseSyntaxNode() {}
-
-	virtual BaseSyntaxNode * clone() const = 0;
-	virtual void accept( Visitor & v ) = 0;
-	virtual void accept( Visitor & v ) const = 0;
-	virtual BaseSyntaxNode * acceptMutator( Mutator & m ) = 0;
-	/// Notes:
-	/// * each node is responsible for indenting its children.
-	/// * Expressions should not finish with a newline, since the expression's parent has better information.
-	virtual void print( std::ostream & os, Indenter indent = {} ) const = 0;
-};
-
-std::ostream & operator<<( std::ostream & out, const BaseSyntaxNode * node );
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/BasicType.cc
===================================================================
--- src/SynTree/BasicType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,40 +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.
-//
-// BasicType.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Aug  4 21:07:44 2019
-// Update Count     : 13
-//
-
-#include <cassert>  // for assert
-#include <list>     // for list
-#include <ostream>  // for operator<<, ostream
-
-#include "Type.h"   // for BasicType, Type, BasicType::Kind, BasicType::Kind...
-
-class Attribute;
-
-BasicType::BasicType( const Type::Qualifiers &tq, Kind bt, const std::list< Attribute * > & attributes ) : Type( tq, attributes ), kind( bt ) {}
-
-void BasicType::print( std::ostream &os, Indenter indent ) const {
-	Type::print( os, indent );
-	os << BasicType::typeNames[ kind ];
-}
-
-bool BasicType::isInteger() const {
-	return kind <= UnsignedInt128;
-}
-
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/CommaExpr.cc
===================================================================
--- src/SynTree/CommaExpr.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,57 +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.
-//
-// CommaExpr.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Arg 12 16:11:00 2016
-// Update Count     : 2
-//
-
-#include <ostream>           // for ostream, endl, operator<<, basic_ostream
-#include <string>            // for operator<<, string
-
-#include "Common/utility.h"  // for maybeClone
-#include "Expression.h"      // for CommaExpr, Expression
-#include "Type.h"            // for Type
-
-CommaExpr::CommaExpr( Expression *arg1, Expression *arg2 )
-		: Expression(), arg1( arg1 ), arg2( arg2 ) {
-	set_result( maybeClone( arg2->get_result() ) );
-}
-
-CommaExpr::CommaExpr( const CommaExpr &other )
-		: Expression( other ), arg1( maybeClone( other.arg1 ) ), arg2( maybeClone( other.arg2 ) ) {
-}
-
-CommaExpr::~CommaExpr() {
-	delete arg1;
-	delete arg2;
-}
-
-bool CommaExpr::get_lvalue() const {
-	// This is wrong by C, but the current implementation uses it.
-	// (ex: Specialize, Lvalue and Box)
-	return arg2->get_lvalue();
-}
-
-void CommaExpr::print( std::ostream &os, Indenter indent ) const {
-	os << "Comma Expression:" << std::endl;
-	os << (indent+1);
-	arg1->print( os, indent+1 );
-	os << std::endl;
-	os << (indent+1);
-	arg2->print( os, indent+1 );
-	Expression::print( os, indent );
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/CompoundStmt.cc
===================================================================
--- src/SynTree/CompoundStmt.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,83 +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.
-//
-// XXX.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Rob Schluntz
-// Last Modified On : Mon May 02 15:19:17 2016
-// Update Count     : 3
-//
-
-#include <cassert>                    // for assert, strict_dynamic_cast
-#include <list>                       // for list, _List_const_iterator, lis...
-#include <ostream>                    // for operator<<, ostream, basic_ostream
-#include <string>                     // for operator==, string
-
-#include "Common/utility.h"           // for cloneAll, deleteAll, printAll
-#include "Declaration.h"              // for DeclarationWithType, Declaration
-#include "Statement.h"                // for CompoundStmt, Statement, DeclStmt
-#include "SynTree/Label.h"            // for Label
-#include "SynTree/DeclReplacer.h"     // for DeclReplacer
-
-using std::string;
-using std::endl;
-
-CompoundStmt::CompoundStmt() : Statement() {
-}
-
-CompoundStmt::CompoundStmt( std::list<Statement *> stmts ) : Statement(), kids( stmts ) {
-}
-
-CompoundStmt::CompoundStmt( const CompoundStmt &other ) : Statement( other ) {
-	cloneAll( other.kids, kids );
-
-	// when cloning a compound statement, we may end up cloning declarations which
-	// are referred to by VariableExprs throughout the block. Cloning a VariableExpr
-	// does a shallow copy, so the VariableExpr will end up pointing to the original
-	// declaration. If the original declaration is deleted, e.g. because the original
-	// CompoundStmt is deleted, then we have a dangling pointer. To avoid this case,
-	// find all DeclarationWithType nodes (since a VariableExpr must point to a
-	// DeclarationWithType) in the original CompoundStmt and map them to the cloned
-	// node in the new CompoundStmt ('this'), then replace the Declarations referred to
-	// by each VariableExpr according to the constructed map. Note that only the declarations
-	// in the current level are collected into the map, because child CompoundStmts will
-	// recursively execute this routine. There may be more efficient ways of doing
-	// this.
-	DeclReplacer::DeclMap declMap;
-	std::list< Statement * >::const_iterator origit = other.kids.begin();
-	for ( Statement * s : kids ) {
-		assert( origit != other.kids.end() );
-		Statement * origStmt = *origit++;
-		if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( s ) ) {
-			DeclStmt * origDeclStmt = strict_dynamic_cast< DeclStmt * >( origStmt );
-			if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * > ( declStmt->get_decl() ) ) {
-				DeclarationWithType * origdwt = strict_dynamic_cast< DeclarationWithType * > ( origDeclStmt->get_decl() );
-				assert( dwt->get_name() == origdwt->get_name() );
-				declMap[ origdwt ] = dwt;
-			} else assert( ! dynamic_cast< DeclarationWithType * > ( origDeclStmt->get_decl() ) );
-		} else assert( ! dynamic_cast< DeclStmt * > ( s ) );
-	}
-	if ( ! declMap.empty() ) {
-		DeclReplacer::replace( this, declMap );
-	}
-}
-
-CompoundStmt::~CompoundStmt() {
-	deleteAll( kids );
-}
-
-void CompoundStmt::print( std::ostream &os, Indenter indent ) const {
-	os << "CompoundStmt" << endl;
-	printAll( kids, os, indent+1 );
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Constant.cc
===================================================================
--- src/SynTree/Constant.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,82 +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.
-//
-// Constant.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb 13 18:11:22 2019
-// Update Count     : 32
-//
-
-#include <cassert>   // for strict_dynamic_cast, assertf
-#include <iostream>  // for operator<<, ostream, basic_ostream
-#include <string>    // for to_string, string, char_traits, operator<<
-
-#include "Constant.h"
-#include "Expression.h" // for ConstantExpr
-#include "Type.h"    // for BasicType, Type, Type::Qualifiers, PointerType
-
-Constant::Constant( Type * type, std::string rep, std::optional<unsigned long long> ival ) : type( type ), rep( rep ), ival( ival ) {}
-
-Constant::Constant( const Constant &other ) : BaseSyntaxNode( other ), rep( other.rep ), ival( other.ival ) {
-	type = other.type->clone();
-}
-
-Constant::~Constant() { delete type; }
-
-Constant Constant::from_bool( bool b ) {
-	return Constant( new BasicType( Type::Qualifiers(), BasicType::Bool ), b ? "1" : "0" , (unsigned long long int)b );
-}
-
-Constant Constant::from_int( int i ) {
-	return Constant( new BasicType( Type::Qualifiers(), BasicType::SignedInt ), std::to_string( i ), (unsigned long long int)i );
-}
-
-Constant Constant::from_ulong( unsigned long i ) {
-	return Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::to_string( i ), (unsigned long long int)i );
-}
-
-Constant Constant::from_string( const std::string & str ) {
-	Type * charType = new BasicType( noQualifiers, BasicType::Char );
-	// Adjust the length of the string for the terminator.
-	Expression * strSize = new ConstantExpr( Constant::from_ulong( str.size() + 1 ) );
-	Type * strType = new ArrayType( noQualifiers, charType, strSize, false, false );
-	const std::string strValue = "\"" + str + "\"";
-	return Constant( strType, strValue, std::nullopt );
-}
-
-Constant Constant::null( Type * ptrtype ) {
-	if ( nullptr == ptrtype ) {
-		ptrtype = new PointerType(
-			Type::Qualifiers(),
-			new VoidType( Type::Qualifiers() )
-			);
-	}
-
-	return Constant( ptrtype, "0", (unsigned long long int)0 );
-}
-
-unsigned long long Constant::get_ival() const {
-	assertf( strict_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve ival from non-integer constant." );
-	return ival.value();
-}
-
-void Constant::print( std::ostream &os, Indenter ) const {
-	os << "(" << rep << " " << (ival ? toString(ival.value()) : "") ;
-	if ( type ) {
-		os << ": ";
-		type->print( os );
-	} // if
-  os << ")";
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Constant.h
===================================================================
--- src/SynTree/Constant.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,69 +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.
-//
-// Constant.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Jul 10 15:57:38 2019
-// Update Count     : 19
-//
-
-#pragma once
-
-#include <iosfwd>     // for ostream
-#include <string>     // for string
-#include <optional>   // for optional
-
-#include "BaseSyntaxNode.h"
-#include "Mutator.h"  // for Mutator
-#include "Visitor.h"  // for Visitor
-
-class Type;
-
-class Constant : public BaseSyntaxNode {
-  public:
-	Constant( Type * type, std::string rep, std::optional<unsigned long long> i );
-	Constant( const Constant & other );
-	Constant & operator=( const Constant & ) = default;
-	virtual ~Constant();
-
-	virtual Constant * clone() const override { return new Constant( *this ); }
-
-	Type * get_type() { return type; }
-	void set_type( Type * newValue ) { type = newValue; }
-	std::string & get_value() { return rep; }
-	void set_value( std::string newValue ) { rep = newValue; }
-	unsigned long long get_ival() const;
-
-	/// generates a boolean constant of the given bool
-	static Constant from_bool( bool b );
-	/// generates an integer constant of the given int
-	static Constant from_int( int i );
-	/// generates an integer constant of the given unsigned long int
-	static Constant from_ulong( unsigned long i );
-	/// generates a string constant from the given string (char type, unquoted string)
-	static Constant from_string( const std::string & string );
-
-	/// generates a null pointer value for the given type. void * if omitted.
-	static Constant null( Type * ptrtype = nullptr );
-
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Constant * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = 0 ) const override;
-
-	Type * type;
-	std::string rep;
-	std::optional<unsigned long long> ival;
-};
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/DeclReplacer.cc
===================================================================
--- src/SynTree/DeclReplacer.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,125 +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.
-//
-// VarExprReplacer.h --
-//
-// Author           : Rob Schluntz
-// Created On       : Wed Jan 13 16:29:30 2016
-// Last Modified By : Rob Schluntz
-// Last Modified On : Fri May 13 11:27:52 2016
-// Update Count     : 5
-//
-
-#include <iostream>       // for operator<<, basic_ostream, ostream, basic_o...
-
-#include "Common/PassVisitor.h"
-#include "Declaration.h"  // for operator<<, DeclarationWithType
-#include "Expression.h"   // for VariableExpr
-#include "DeclReplacer.h"
-
-namespace DeclReplacer {
-	namespace {
-		/// Visitor that replaces the declarations that VariableExprs refer to, according to the supplied mapping
-		struct DeclReplacer {
-		private:
-			const DeclMap & declMap;
-			const TypeMap & typeMap;
-			bool debug;
-		public:
-			size_t replaced;
-
-		public:
-			DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
-
-			// replace variable with new node from decl map
-			void previsit( VariableExpr * varExpr );
-
-			// replace type inst with new node from type map
-			void previsit( TypeInstType * inst );
-		};
-
-		/// Mutator that replaces uses of declarations with arbitrary expressions, according to the supplied mapping
-		struct ExprDeclReplacer {
-		private:
-			const ExprMap & exprMap;
-			bool debug;
-		public:
-			size_t replaced;
-
-		public:
-			ExprDeclReplacer( const ExprMap & exprMap, bool debug = false );
-
-			// replace variable with new node from expr map
-			Expression * postmutate( VariableExpr * varExpr );
-		};
-	}
-
-	size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug ) {
-		PassVisitor<DeclReplacer> replacer( declMap, typeMap, debug );
-		maybeAccept( node, replacer );
-		return replacer.pass.replaced;
-	}
-
-	size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug ) {
-		TypeMap typeMap;
-		return replace( node, declMap, typeMap, debug );
-	}
-
-	size_t replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug ) {
-		DeclMap declMap;
-		return replace( node, declMap, typeMap, debug );
-	}
-
-	size_t replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug ) {
-		PassVisitor<ExprDeclReplacer> replacer( exprMap, debug );
-		node = maybeMutate( node, replacer );
-		return replacer.pass.replaced;
-	}
-
-	namespace {
-		DeclReplacer::DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug ) : declMap( declMap ), typeMap( typeMap ) , debug( debug ), replaced( 0 ) {}
-
-		// replace variable with new node from decl map
-		void DeclReplacer::previsit( VariableExpr * varExpr ) {
-			// xxx - assertions and parameters aren't accounted for in this... (i.e. they aren't inserted into the map when it's made, only DeclStmts are)
-			if ( declMap.count( varExpr->var ) ) {
-				replaced++;
-				auto replacement = declMap.at( varExpr->var );
-				if ( debug ) {
-					std::cerr << "replacing variable reference: " << (void*)varExpr->var << " " << varExpr->var << " with " << (void*)replacement << " " << replacement << std::endl;
-				}
-				varExpr->var = replacement;
-			}
-		}
-
-		void DeclReplacer::previsit( TypeInstType * inst ) {
-			if ( typeMap.count( inst->baseType ) ) {
-				replaced++;
-				auto replacement = typeMap.at( inst->baseType );
-				if ( debug ) {
-					std::cerr << "replacing type reference: " << (void*)inst->baseType << " " << inst->baseType << " with " << (void*)replacement << " " << replacement << std::endl;
-				}
-				inst->baseType = replacement;
-			}
-		}
-
-		ExprDeclReplacer::ExprDeclReplacer( const ExprMap & exprMap, bool debug ) : exprMap( exprMap ), debug( debug ), replaced( 0 ) {}
-
-		Expression * ExprDeclReplacer::postmutate( VariableExpr * varExpr ) {
-			if ( exprMap.count( varExpr->var ) ) {
-				replaced++;
-				Expression * replacement = exprMap.at( varExpr->var )->clone();
-				if ( debug ) {
-					std::cerr << "replacing variable reference: " << (void*)varExpr->var << " " << varExpr->var << " with " << (void*)replacement << " " << replacement << std::endl;
-				}
-				std::swap( varExpr->env, replacement->env );
-				delete varExpr;
-				return replacement;
-			}
-			return varExpr;
-		}
-	}
-} // namespace VarExprReplacer
Index: c/SynTree/DeclReplacer.h
===================================================================
--- src/SynTree/DeclReplacer.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,51 +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.
-//
-// VarExprReplacer.h --
-//
-// Author           : Rob Schluntz
-// Created On       : Wed Jan 13 16:29:30 2016
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:53:41 2017
-// Update Count     : 6
-//
-
-#pragma once
-
-#include <map>                // for map, map<>::value_compare
-
-#include "SynTree/Visitor.h"  // for Visitor
-
-class DeclarationWithType;
-class VariableExpr;
-
-namespace DeclReplacer {
-	typedef std::map< DeclarationWithType *, DeclarationWithType * > DeclMap;
-	typedef std::map< TypeDecl *, TypeDecl * > TypeMap;
-	typedef std::map< DeclarationWithType *, Expression * > ExprMap;
-
-	size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug = false );
-	size_t replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug = false );
-	size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
-
-	size_t replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug = false);
-
-	template<typename T>
-	size_t replace( T *& node, const ExprMap & exprMap, bool debug = false ) {
-		if ( ! node ) return 0ul;
-		BaseSyntaxNode * arg = node;
-		size_t replaced = replace( arg, exprMap, debug );
-		node = dynamic_cast<T *>( arg );
-		assertf( node, "DeclReplacer fundamentally changed the type of its argument." );
-		return replaced;
-	}
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/DeclStmt.cc
===================================================================
--- src/SynTree/DeclStmt.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,45 +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.
-//
-// DeclStmt.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jun 23 11:38:15 2015
-// Update Count     : 4
-//
-
-#include <cassert>           // for assert
-#include <list>              // for list
-#include <ostream>           // for operator<<, ostream
-
-#include "Common/utility.h"  // for maybeClone
-#include "Declaration.h"     // for Declaration
-#include "Statement.h"       // for DeclStmt, Statement
-#include "SynTree/Label.h"   // for Label
-
-DeclStmt::DeclStmt( Declaration *decl ) : Statement(), decl( decl ) {
-}
-
-DeclStmt::DeclStmt( const DeclStmt &other ) : Statement( other ), decl( maybeClone( other.decl ) ) {
-}
-
-DeclStmt::~DeclStmt() {
-	delete decl;
-}
-
-void DeclStmt::print( std::ostream &os, Indenter indent ) const {
-	assert( decl != 0 );
-	os << "Declaration of ";
-	decl->print( os, indent );
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Declaration.cc
===================================================================
--- src/SynTree/Declaration.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,115 +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.
-//
-// Declaration.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 12 18:35:39 2021
-// Update Count     : 37
-//
-
-#include <map>                       // for _Rb_tree_const_iterator, map<>::...
-#include <ostream>                   // for ostream, operator<<, basic_ostre...
-#include <string>                    // for string
-#include <utility>                   // for pair
-
-#include "Common/utility.h"          // for maybeClone
-#include "Declaration.h"
-#include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
-#include "SynTree/Statement.h"       // for AsmStmt
-#include "SynTree/SynTree.h"         // for UniqueId
-#include "SynTree/Expression.h"
-#include "Type.h"                    // for Type, Type::StorageClasses
-
-// To canonicalize declarations
-static UniqueId lastUniqueId = 0;
-
-Declaration::Declaration( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage )
-		: name( name ), linkage( linkage ), uniqueId( 0 ), storageClasses( scs ) {
-}
-
-Declaration::Declaration( const Declaration &other )
-	: BaseSyntaxNode( other ), name( other.name ), linkage( other.linkage ), extension( other.extension ), uniqueId( other.uniqueId ), storageClasses( other.storageClasses ) {
-}
-
-Declaration::~Declaration() {
-}
-
-void Declaration::fixUniqueId() {
-	// don't need to set unique ID twice
-	if ( uniqueId ) return;
-	uniqueId = ++lastUniqueId;
-}
-
-AsmDecl::AsmDecl( AsmStmt *stmt ) : Declaration( "", Type::StorageClasses(), LinkageSpec::C ), stmt( stmt ) {
-}
-
-AsmDecl::AsmDecl( const AsmDecl &other ) : Declaration( other ), stmt( maybeClone( other.stmt ) ) {
-}
-
-AsmDecl::~AsmDecl() {
-	delete stmt;
-}
-
-void AsmDecl::print( std::ostream &os, Indenter indent ) const {
-	stmt->print( os, indent );
-}
-
-void AsmDecl::printShort( std::ostream &os, Indenter indent ) const {
-	stmt->print( os, indent );
-}
-
-
-DirectiveDecl::DirectiveDecl( DirectiveStmt *stmt ) : Declaration( "", Type::StorageClasses(), LinkageSpec::C ), stmt( stmt ) {
-}
-
-DirectiveDecl::DirectiveDecl( const DirectiveDecl &other ) : Declaration( other ), stmt( maybeClone( other.stmt ) ) {
-}
-
-DirectiveDecl::~DirectiveDecl() {
-	delete stmt;
-}
-
-void DirectiveDecl::print( std::ostream &os, Indenter indent ) const {
-	stmt->print( os, indent );
-}
-
-void DirectiveDecl::printShort( std::ostream &os, Indenter indent ) const {
-	stmt->print( os, indent );
-}
-
-
-StaticAssertDecl::StaticAssertDecl( Expression * condition, ConstantExpr * message ) : Declaration( "", Type::StorageClasses(), LinkageSpec::C ), condition( condition ), message( message )  {
-}
-
-StaticAssertDecl::StaticAssertDecl( const StaticAssertDecl & other ) : Declaration( other ), condition( maybeClone( other.condition ) ), message( maybeClone( other.message ) )  {
-}
-
-StaticAssertDecl::~StaticAssertDecl() {
-	delete condition;
-	delete message;
-}
-
-void StaticAssertDecl::print( std::ostream &os, Indenter indent ) const {
-	os << "Static Assert with condition: ";
-	condition->print( os, indent+1 );
-	os << std::endl << indent << "and message: ";
-	message->print( os, indent+1 );
-os << std::endl;
-}
-
-void StaticAssertDecl::printShort( std::ostream &os, Indenter indent ) const {
-	print( os, indent );
-}
-
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,483 +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.
-//
-// Declaration.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Henry Xue
-// Last Modified On : Tue Jul 20 04:10:50 2021
-// Update Count     : 160
-//
-
-#pragma once
-
-#include <cassert>               // for assertf
-#include <iosfwd>                // for ostream
-#include <list>                  // for list
-#include <unordered_map>         // for unordered_map
-#include <string>                // for string, operator+, allocator, to_string
-
-#include "BaseSyntaxNode.h"      // for BaseSyntaxNode
-#include "Mutator.h"             // for Mutator
-#include "LinkageSpec.h"         // for Spec, Cforall
-#include "SynTree.h"             // for UniqueId
-#include "SynTree/Type.h"        // for Type, Type::StorageClasses, Type::Fu...
-#include "Visitor.h"             // for Visitor
-
-class AsmStmt;
-class Attribute;
-class CompoundStmt;
-class ConstantExpr;
-class Expression;
-class Initializer;
-class TypeDecl;
-
-class Declaration : public BaseSyntaxNode {
-  public:
-	std::string name;
-	LinkageSpec::Spec linkage;
-	bool extension = false;
-
-	Declaration( const std::string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage );
-	Declaration( const Declaration & other );
-	virtual ~Declaration();
-
-	const std::string & get_name() const { return name; }
-	void set_name( std::string newValue ) { name = newValue; }
-
-	Type::StorageClasses get_storageClasses() const { return storageClasses; }
-
-	LinkageSpec::Spec get_linkage() const { return linkage; }
-	void set_linkage( LinkageSpec::Spec newValue ) { linkage = newValue; }
-
-	UniqueId get_uniqueId() const { return uniqueId; }
-
-	bool get_extension() const { return extension; }
-	Declaration * set_extension( bool exten ) { extension = exten; return this; }
-
-	void fixUniqueId( void );
-	virtual Declaration * clone() const override = 0;
-	virtual void accept( Visitor & v ) override = 0;
-	virtual void accept( Visitor & v ) const override = 0;
-	virtual Declaration * acceptMutator( Mutator & m ) override = 0;
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override = 0;
-	virtual void printShort( std::ostream & os, Indenter indent = {} ) const = 0;
-
-	UniqueId uniqueId;
-	Type::StorageClasses storageClasses;
-  private:
-};
-
-class DeclarationWithType : public Declaration {
-  public:
-	// this represents the type with all types and typedefs expanded it is generated by SymTab::Validate::Pass2
-	std::string mangleName;
-	// need to remember the scope level at which the variable was declared, so that shadowed identifiers can be accessed
-	int scopeLevel = 0;
-
-	Expression * asmName;
-	std::list< Attribute * > attributes;
-	bool isDeleted = false;
-
-	DeclarationWithType( const std::string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage, const std::list< Attribute * > & attributes, Type::FuncSpecifiers fs );
-	DeclarationWithType( const DeclarationWithType & other );
-	virtual ~DeclarationWithType();
-
-	std::string get_mangleName() const { return mangleName; }
-	DeclarationWithType * set_mangleName( std::string newValue ) { mangleName = newValue; return this; }
-
-	std::string get_scopedMangleName() const { return mangleName + "_" + std::to_string(scopeLevel); }
-
-	int get_scopeLevel() const { return scopeLevel; }
-	DeclarationWithType * set_scopeLevel( int newValue ) { scopeLevel = newValue; return this; }
-
-	Expression * get_asmName() const { return asmName; }
-	DeclarationWithType * set_asmName( Expression * newValue ) { asmName = newValue; return this; }
-
-	std::list< Attribute * >& get_attributes() { return attributes; }
-	const std::list< Attribute * >& get_attributes() const { return attributes; }
-
-	Type::FuncSpecifiers get_funcSpec() const { return fs; }
-	//void set_functionSpecifiers( Type::FuncSpecifiers newValue ) { fs = newValue; }
-
-	virtual DeclarationWithType * clone() const override = 0;
-	virtual DeclarationWithType * acceptMutator( Mutator & m )  override = 0;
-
-	virtual Type * get_type() const = 0;
-	virtual void set_type(Type *) = 0;
-
-  private:
-	Type::FuncSpecifiers fs;
-};
-
-class ObjectDecl : public DeclarationWithType {
-	typedef DeclarationWithType Parent;
-  public:
-	Type * type;
-	Initializer * init;
-	Expression * bitfieldWidth;
-	bool enumInLine = false;
-
-	ObjectDecl( const std::string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage, Expression * bitfieldWidth, Type * type, Initializer * init,
-				const std::list< Attribute * > attributes = std::list< Attribute * >(), Type::FuncSpecifiers fs = Type::FuncSpecifiers() );
-	ObjectDecl( const ObjectDecl & other );
-	virtual ~ObjectDecl();
-
-	virtual Type * get_type() const override { return type; }
-	virtual void set_type(Type * newType) override { type = newType; }
-
-	Initializer * get_init() const { return init; }
-	void set_init( Initializer * newValue ) { init = newValue; }
-
-	Expression * get_bitfieldWidth() const { return bitfieldWidth; }
-	void set_bitfieldWidth( Expression * newValue ) { bitfieldWidth = newValue; }
-
-	static ObjectDecl * newObject( const std::string & name, Type * type, Initializer * init );
-
-	virtual ObjectDecl * clone() const override { return new ObjectDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual DeclarationWithType * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-	virtual void printShort( std::ostream & os, Indenter indent = {} ) const override;
-
-	void checkAssignedValue() const;
-};
-
-class FunctionDecl : public DeclarationWithType {
-	typedef DeclarationWithType Parent;
-  public:
-	FunctionType * type;
-	CompoundStmt * statements;
-	std::list< Expression * > withExprs;
-
-	FunctionDecl( const std::string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage, FunctionType * type, CompoundStmt * statements,
-				  const std::list< Attribute * > attributes = std::list< Attribute * >(), Type::FuncSpecifiers fs = Type::FuncSpecifiers() );
-	FunctionDecl( const FunctionDecl & other );
-	virtual ~FunctionDecl();
-
-	virtual Type * get_type() const override { return type; }
-	virtual void set_type(Type * t) override { type = strict_dynamic_cast< FunctionType* >( t ); }
-
-	FunctionType * get_functionType() const { return type; }
-	void set_functionType( FunctionType * newValue ) { type = newValue; }
-	CompoundStmt * get_statements() const { return statements; }
-	void set_statements( CompoundStmt * newValue ) { statements = newValue; }
-	bool has_body() const { return NULL != statements; }
-
-	static FunctionDecl * newFunction( const std::string & name, FunctionType * type, CompoundStmt * statements );
-
-	virtual FunctionDecl * clone() const override { return new FunctionDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual DeclarationWithType * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-	virtual void printShort( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class NamedTypeDecl : public Declaration {
-	typedef Declaration Parent;
-  public:
-	Type * base;
-	std::list< DeclarationWithType * > assertions;
-
-	NamedTypeDecl( const std::string & name, Type::StorageClasses scs, Type * type );
-	NamedTypeDecl( const NamedTypeDecl & other );
-	virtual ~NamedTypeDecl();
-
-	Type * get_base() const { return base; }
-	void set_base( Type * newValue ) { base = newValue; }
-	std::list< DeclarationWithType * >& get_assertions() { return assertions; }
-
-	virtual const char * typeString() const = 0;
-
-	virtual NamedTypeDecl * clone() const override = 0;
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-	virtual void printShort( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class TypeDecl : public NamedTypeDecl {
-	typedef NamedTypeDecl Parent;
-  public:
-	enum Kind { Dtype, DStype, Otype, Ftype, Ttype, Dimension, NUMBER_OF_KINDS };
-
-	Kind kind;
-	bool sized;
-	Type * init;
-
-	/// Data extracted from a type decl
-	struct Data {
-		Kind kind;
-		bool isComplete;
-
-		Data() : kind( NUMBER_OF_KINDS ), isComplete( false ) {}
-		Data( const TypeDecl * typeDecl ) : Data( typeDecl->get_kind(), typeDecl->isComplete() ) {}
-		Data( Kind kind, bool isComplete ) : kind( kind ), isComplete( isComplete ) {}
-		Data( const Data & d1, const Data & d2 )
-			: kind( d1.kind ), isComplete( d1.isComplete || d2.isComplete ) {}
-
-		bool operator==( const Data & other ) const { return kind == other.kind && isComplete == other.isComplete; }
-		bool operator!=( const Data & other ) const { return !(*this == other);}
-	};
-
-	TypeDecl( const std::string & name, Type::StorageClasses scs, Type * type, Kind kind, bool sized, Type * init = nullptr );
-	TypeDecl( const TypeDecl & other );
-	virtual ~TypeDecl();
-
-	Kind get_kind() const { return kind; }
-
-	Type * get_init() const { return init; }
-	TypeDecl * set_init( Type * newValue ) { init = newValue; return this; }
-
-	bool isComplete() const { return sized; }
-	bool get_sized() const { return sized; }
-	TypeDecl * set_sized( bool newValue ) { sized = newValue; return this; }
-
-	virtual const char * typeString() const override;
-	virtual const char * genTypeString() const;
-
-	virtual TypeDecl * clone() const override { return new TypeDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Declaration * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class TypedefDecl : public NamedTypeDecl {
-	typedef NamedTypeDecl Parent;
-  public:
-	TypedefDecl( const std::string & name, CodeLocation location, Type::StorageClasses scs, Type * type, LinkageSpec::Spec spec = LinkageSpec::Cforall )
-		: Parent( name, scs, type ) { set_linkage( spec ); this->location = location; }
-
-	TypedefDecl( const TypedefDecl & other ) : Parent( other ) {}
-
-	virtual const char * typeString() const override;
-
-	virtual TypedefDecl * clone() const override { return new TypedefDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Declaration * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-  private:
-};
-
-class AggregateDecl : public Declaration {
-	typedef Declaration Parent;
-  public:
-	enum Aggregate { Struct, Union, Enum, Exception, Trait, Generator, Coroutine, Monitor, Thread, NoAggregate };
-	static const char * aggrString( Aggregate aggr );
-
-	std::list<Declaration*> members;
-	std::list<TypeDecl*> parameters;
-	bool body;
-	std::list< Attribute * > attributes;
-	AggregateDecl * parent = nullptr;
-
-	AggregateDecl( const std::string & name, const std::list< Attribute * > & attributes = std::list< class Attribute * >(), LinkageSpec::Spec linkage = LinkageSpec::Cforall );
-	AggregateDecl( const AggregateDecl & other );
-	virtual ~AggregateDecl();
-
-	std::list<Declaration*>& get_members() { return members; }
-	std::list<TypeDecl*>& get_parameters() { return parameters; }
-
-	std::list< Attribute * >& get_attributes() { return attributes; }
-	const std::list< Attribute * >& get_attributes() const { return attributes; }
-
-	bool has_body() const { return body; }
-	AggregateDecl * set_body( bool body ) { AggregateDecl::body = body; return this; }
-
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-	virtual void printShort( std::ostream & os, Indenter indent = {} ) const override;
-  protected:
-	virtual const char * typeString() const = 0;
-};
-
-class StructDecl : public AggregateDecl {
-	typedef AggregateDecl Parent;
-  public:
-	StructDecl( const std::string & name, Aggregate kind = Struct, const std::list< Attribute * > & attributes = std::list< class Attribute * >(), LinkageSpec::Spec linkage = LinkageSpec::Cforall ) : Parent( name, attributes, linkage ), kind( kind ) {}
-	StructDecl( const StructDecl & other ) : Parent( other ), kind( other.kind ) {}
-
-	bool is_coroutine() { return kind == Coroutine; }
-	bool is_exception() { return kind == Exception; }
-	bool is_generator() { return kind == Generator; }
-	bool is_monitor  () { return kind == Monitor  ; }
-	bool is_thread   () { return kind == Thread   ; }
-
-	// Make a type instance of this declaration.
-	StructInstType * makeInst( std::list< Expression * > const & parameters );
-	StructInstType * makeInst( std::list< Expression * > && parameters );
-
-	virtual StructDecl * clone() const override { return new StructDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Declaration * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	Aggregate kind;
-  private:
-	virtual const char * typeString() const override;
-};
-
-class UnionDecl : public AggregateDecl {
-	typedef AggregateDecl Parent;
-  public:
-	UnionDecl( const std::string & name, const std::list< Attribute * > & attributes = std::list< class Attribute * >(), LinkageSpec::Spec linkage = LinkageSpec::Cforall ) : Parent( name, attributes, linkage ) {}
-	UnionDecl( const UnionDecl & other ) : Parent( other ) {}
-
-	virtual UnionDecl * clone() const override { return new UnionDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Declaration * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-  private:
-	virtual const char * typeString() const override;
-};
-
-class EnumDecl : public AggregateDecl {
-	typedef AggregateDecl Parent;
-  public:
-  	bool isTyped;
-	Type * base;
-	enum EnumHiding { Visible, Hide } hide;
-
-	EnumDecl( const std::string & name,
-	 const std::list< Attribute * > & attributes = std::list< class Attribute * >(),
-	  bool isTyped = false, LinkageSpec::Spec linkage = LinkageSpec::Cforall,
-	  Type * baseType = nullptr ) 
-	  : Parent( name, attributes, linkage ), isTyped(isTyped), base( baseType ) {}
-	EnumDecl( const EnumDecl & other ) 
-	  : Parent( other ), isTyped( other.isTyped), base( other.base ) {}
-	bool valueOf( Declaration * enumerator, long long int & value );
-	virtual EnumDecl * clone() const override { return new EnumDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Declaration * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-
-	std::unordered_map< std::string, long long int > enumValues; // This attribute is unused
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override final;
-  private:
-	// std::unordered_map< std::string, long long int > enumValues;
-	virtual const char * typeString() const override;
-};
-
-class TraitDecl : public AggregateDecl {
-	typedef AggregateDecl Parent;
-  public:
-	TraitDecl( const std::string & name, const std::list< Attribute * > & attributes, LinkageSpec::Spec linkage ) : Parent( name, attributes, linkage ) {
-		assertf( attributes.empty(), "attribute unsupported for traits" );
-	}
-	TraitDecl( const TraitDecl & other ) : Parent( other ) {}
-
-	virtual TraitDecl * clone() const override { return new TraitDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Declaration * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-  private:
-	virtual const char * typeString() const override;
-};
-
-class WithStmt : public Declaration {
-public:
-	std::list< Expression * > exprs;
-	Statement * stmt;
-
-	WithStmt( const std::list< Expression * > & exprs, Statement * stmt );
-	WithStmt( const WithStmt & other );
-	virtual ~WithStmt();
-
-	virtual WithStmt * clone() const override { return new WithStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Declaration * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-	virtual void printShort( std::ostream & os, Indenter indent = {} ) const override { print(os, indent); }
-};
-
-class AsmDecl : public Declaration {
-  public:
-	AsmStmt * stmt;
-
-	AsmDecl( AsmStmt * stmt );
-	AsmDecl( const AsmDecl & other );
-	virtual ~AsmDecl();
-
-	AsmStmt * get_stmt() { return stmt; }
-	void set_stmt( AsmStmt * newValue ) { stmt = newValue; }
-
-	virtual AsmDecl * clone() const override { return new AsmDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual AsmDecl * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-	virtual void printShort( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class DirectiveDecl : public Declaration {
-  public:
-	DirectiveStmt * stmt;
-
-	DirectiveDecl( DirectiveStmt * stmt );
-	DirectiveDecl( const DirectiveDecl & other );
-	virtual ~DirectiveDecl();
-
-	DirectiveStmt * get_stmt() { return stmt; }
-	void set_stmt( DirectiveStmt * newValue ) { stmt = newValue; }
-
-	virtual DirectiveDecl * clone() const override { return new DirectiveDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual DirectiveDecl * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-	virtual void printShort( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class StaticAssertDecl : public Declaration {
-public:
-	Expression * condition;
-	ConstantExpr * message;   // string literal
-
-	StaticAssertDecl( Expression * condition, ConstantExpr * message );
-	StaticAssertDecl( const StaticAssertDecl & other );
-	virtual ~StaticAssertDecl();
-
-	virtual StaticAssertDecl * clone() const override { return new StaticAssertDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual StaticAssertDecl * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-	virtual void printShort( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-
-class InlineMemberDecl : public DeclarationWithType {
-	typedef DeclarationWithType Parent;
-  public:
-	Type * type;
-
-	InlineMemberDecl( const std::string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage, Type * type,
-				const std::list< Attribute * > attributes = std::list< Attribute * >(), Type::FuncSpecifiers fs = Type::FuncSpecifiers() );
-	InlineMemberDecl( const InlineMemberDecl & other );
-	virtual ~InlineMemberDecl();
-
-	virtual Type * get_type() const override { return type; }
-	virtual void set_type(Type * newType) override { type = newType; }
-
-	static InlineMemberDecl * newInlineMemberDecl( const std::string & name, Type * type );
-
-	virtual InlineMemberDecl * clone() const override { return new InlineMemberDecl( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual DeclarationWithType * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-	virtual void printShort( std::ostream & os, Indenter indent = {} ) const override;
-
-};
-
-std::ostream & operator<<( std::ostream & os, const TypeDecl::Data & data );
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/DeclarationWithType.cc
===================================================================
--- src/SynTree/DeclarationWithType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,45 +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.
-//
-// DeclarationWithType.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Dec 13 23:45:16 2019
-// Update Count     : 26
-//
-
-#include <list>                  // for list
-#include <string>                // for string
-
-#include "Attribute.h"           // for Attribute
-#include "Common/utility.h"      // for cloneAll, deleteAll, maybeClone
-#include "Declaration.h"         // for DeclarationWithType, Declaration
-#include "LinkageSpec.h"         // for Spec
-#include "Expression.h"          // for ConstantExpr
-#include "Type.h"                // for Type, Type::FuncSpecifiers, Type::St...
-
-DeclarationWithType::DeclarationWithType( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage, const std::list< Attribute * > & attributes, Type::FuncSpecifiers fs )
-	: Declaration( name, scs, linkage ), asmName( nullptr ), attributes( attributes ), fs( fs ) {
-}
-
-DeclarationWithType::DeclarationWithType( const DeclarationWithType &other )
-		: Declaration( other ), mangleName( other.mangleName ), scopeLevel( other.scopeLevel ), fs( other.fs ) {
-	cloneAll( other.attributes, attributes );
-	asmName = maybeClone( other.asmName );
-}
-
-DeclarationWithType::~DeclarationWithType() {
-	deleteAll( attributes );
-	delete asmName;
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,804 +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.
-//
-// Expression.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Dec 11 07:55:15 2019
-// Update Count     : 70
-//
-
-#include "SynTree/Expression.h"
-
-#include <cassert>                   // for assert, assertf
-#include <iostream>                  // for ostream, operator<<, basic_ostream
-#include <list>                      // for list, _List_iterator, list<>::co...
-#include <set>                       // for set
-
-#include "Common/utility.h"          // for maybeClone, cloneAll, deleteAll
-#include "Expression.h"              // for Expression, ImplicitCopyCtorExpr
-#include "InitTweak/InitTweak.h"     // for getCallArg, getPointerBase
-#include "Initializer.h"             // for Designation, Initializer
-#include "Statement.h"               // for CompoundStmt, ExprStmt, Statement
-#include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
-#include "SynTree/Constant.h"        // for Constant
-#include "Type.h"                    // for Type, BasicType, Type::Qualifiers
-#include "TypeSubstitution.h"        // for TypeSubstitution
-#include "CompilationState.h"        // for deterministic_output
-
-#include "GenPoly/Lvalue.h"
-
-void printInferParams( const InferredParams & inferParams, std::ostream & os, Indenter indent, int level ) {
-	if ( ! inferParams.empty() ) {
-		os << indent << "with inferred parameters " << level << ":" << std::endl;
-		for ( InferredParams::const_iterator i = inferParams.begin(); i != inferParams.end(); ++i ) {
-			os << indent+1;
-			assert(i->second.declptr);
-			i->second.declptr->printShort( os, indent+1 );
-			os << std::endl;
-			printInferParams( i->second.expr->inferParams, os, indent+1, level+1 );
-		} // for
-	} // if
-}
-
-Expression::Expression() : result( 0 ), env( 0 ) {}
-
-Expression::Expression( const Expression & other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ), inferParams( other.inferParams ), resnSlots( other.resnSlots ) {}
-
-void Expression::spliceInferParams( Expression * other ) {
-	if ( ! other ) return;
-	for ( auto p : other->inferParams ) {
-		inferParams[p.first] = std::move( p.second );
-	}
-	resnSlots.insert( resnSlots.end(), other->resnSlots.begin(), other->resnSlots.end() );
-}
-
-Expression::~Expression() {
-	delete env;
-	delete result;
-}
-
-bool Expression::get_lvalue() const {
-	return false;
-}
-
-void Expression::print( std::ostream & os, Indenter indent ) const {
-	printInferParams( inferParams, os, indent+1, 0 );
-
-	if ( result ) {
-		os << std::endl << indent << "with resolved type:" << std::endl;
-		os << (indent+1);
-		result->print( os, indent+1 );
-	}
-
-	if ( env ) {
-		os << std::endl << indent << "... with environment:" << std::endl;
-		env->print( os, indent+1 );
-	} // if
-
-	if ( extension ) {
-		os << std::endl << indent << "... with extension:";
-	} // if
-}
-
-ConstantExpr::ConstantExpr( Constant _c ) : Expression(), constant( _c ) {
-	set_result( constant.get_type()->clone() );
-}
-
-ConstantExpr::ConstantExpr( const ConstantExpr & other) : Expression( other ), constant( other.constant ) {
-}
-
-ConstantExpr::~ConstantExpr() {}
-
-void ConstantExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "constant expression " ;
-	constant.print( os );
-	Expression::print( os, indent );
-}
-
-long long int ConstantExpr::intValue() const {
-	if ( BasicType * basicType = dynamic_cast< BasicType * >( result ) ) {
-		if ( basicType->isInteger() ) {
-			return get_constant()->get_ival();
-		}
-	} else if ( dynamic_cast< OneType * >( result ) ) {
-		return 1;
-	} else if ( dynamic_cast< ZeroType * >( result ) ) {
-		return 0;
-	}
-	SemanticError( this, "Constant expression of non-integral type " );
-}
-
-VariableExpr::VariableExpr() : Expression(), var( nullptr ) {}
-
-VariableExpr::VariableExpr( DeclarationWithType *_var ) : Expression(), var( _var ) {
-	assert( var );
-	assert( var->get_type() );
-	Type * type = var->get_type()->clone();
-
-	// xxx - doesn't quite work yet - get different alternatives with the same cost
-
-	// // enumerators are not lvalues
-	// if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( var->get_type() ) ) {
-	// 	assert( inst->baseEnum );
-	// 	EnumDecl * decl = inst->baseEnum;
-	// 	long long int value;
-	// 	if ( decl->valueOf( var, value ) ) {
-	// 		type->set_lvalue( false ); // Would have to move to get_lvalue.
-	// 	}
-	// }
-
-	set_result( type );
-}
-
-VariableExpr::VariableExpr( const VariableExpr & other ) : Expression( other ), var( other.var ) {
-}
-
-VariableExpr::~VariableExpr() {
-	// don't delete the declaration, since it points somewhere else in the tree
-}
-
-bool VariableExpr::get_lvalue() const {
-	// It isn't always an lvalue, but it is never an rvalue.
-	return true;
-}
-
-VariableExpr * VariableExpr::functionPointer( FunctionDecl * func ) {
-	VariableExpr * funcExpr = new VariableExpr( func );
-	funcExpr->set_result( new PointerType( Type::Qualifiers(), funcExpr->get_result() ) );
-	return funcExpr;
-}
-
-void VariableExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Variable Expression: ";
-	var->printShort(os, indent);
-	Expression::print( os, indent );
-}
-
-SizeofExpr::SizeofExpr( Expression * expr_ ) :
-		Expression(), expr(expr_), type(0), isType(false) {
-	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
-}
-
-SizeofExpr::SizeofExpr( Type * type_ ) :
-		Expression(), expr(0), type(type_), isType(true) {
-	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
-}
-
-SizeofExpr::SizeofExpr( const SizeofExpr & other ) :
-	Expression( other ), expr( maybeClone( other.expr ) ), type( maybeClone( other.type ) ), isType( other.isType ) {
-}
-
-SizeofExpr::~SizeofExpr() {
-	delete expr;
-	delete type;
-}
-
-void SizeofExpr::print( std::ostream & os, Indenter indent) const {
-	os << "Sizeof Expression on: ";
-	if (isType) type->print(os, indent+1);
-	else expr->print(os, indent+1);
-	Expression::print( os, indent );
-}
-
-AlignofExpr::AlignofExpr( Expression * expr_ ) :
-		Expression(), expr(expr_), type(0), isType(false) {
-	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
-}
-
-AlignofExpr::AlignofExpr( Type * type_ ) :
-		Expression(), expr(0), type(type_), isType(true) {
-	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
-}
-
-AlignofExpr::AlignofExpr( const AlignofExpr & other ) :
-	Expression( other ), expr( maybeClone( other.expr ) ), type( maybeClone( other.type ) ), isType( other.isType ) {
-}
-
-AlignofExpr::~AlignofExpr() {
-	delete expr;
-	delete type;
-}
-
-void AlignofExpr::print( std::ostream & os, Indenter indent) const {
-	os << "Alignof Expression on: ";
-	if (isType) type->print(os, indent+1);
-	else expr->print(os, indent+1);
-	Expression::print( os, indent );
-}
-
-UntypedOffsetofExpr::UntypedOffsetofExpr( Type * type, const std::string & member ) :
-		Expression(), type(type), member(member) {
-	assert( type );
-	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
-}
-
-UntypedOffsetofExpr::UntypedOffsetofExpr( const UntypedOffsetofExpr & other ) :
-	Expression( other ), type( maybeClone( other.type ) ), member( other.member ) {}
-
-UntypedOffsetofExpr::~UntypedOffsetofExpr() {
-	delete type;
-}
-
-void UntypedOffsetofExpr::print( std::ostream & os, Indenter indent) const {
-	os << "Untyped Offsetof Expression on member " << member << " of ";
-	type->print(os, indent+1);
-	Expression::print( os, indent );
-}
-
-OffsetofExpr::OffsetofExpr( Type * type, DeclarationWithType * member ) :
-		Expression(), type(type), member(member) {
-	assert( member );
-	assert( type );
-	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
-}
-
-OffsetofExpr::OffsetofExpr( const OffsetofExpr & other ) :
-	Expression( other ), type( maybeClone( other.type ) ), member( other.member ) {}
-
-OffsetofExpr::~OffsetofExpr() {
-	delete type;
-}
-
-void OffsetofExpr::print( std::ostream & os, Indenter indent) const {
-	os << "Offsetof Expression on member " << member->name << " of ";
-	type->print(os, indent+1);
-	Expression::print( os, indent );
-}
-
-OffsetPackExpr::OffsetPackExpr( StructInstType * type ) : Expression(), type( type ) {
-	assert( type );
-	set_result( new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0, false, false ) );
-}
-
-OffsetPackExpr::OffsetPackExpr( const OffsetPackExpr & other ) : Expression( other ), type( maybeClone( other.type ) ) {}
-
-OffsetPackExpr::~OffsetPackExpr() { delete type; }
-
-void OffsetPackExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Offset pack expression on ";
-	type->print(os, indent+1);
-	Expression::print( os, indent );
-}
-
-CastExpr::CastExpr( Expression * arg, Type * toType, bool isGenerated, CastKind kind ) : arg(arg), isGenerated( isGenerated ), kind( kind ) {
-	set_result(toType);
-}
-
-CastExpr::CastExpr( Expression * arg, bool isGenerated, CastKind kind ) : arg(arg), isGenerated( isGenerated ), kind( kind ) {
-	set_result( new VoidType( Type::Qualifiers() ) );
-}
-
-CastExpr::CastExpr( const CastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), isGenerated( other.isGenerated ), kind( other.kind ) {
-}
-
-CastExpr::~CastExpr() {
-	delete arg;
-}
-
-bool CastExpr::get_lvalue() const {
-	// This is actually wrong by C, but it works with our current set-up.
-	return arg->get_lvalue();
-}
-
-void CastExpr::print( std::ostream & os, Indenter indent ) const {
-	os << (isGenerated ? "Generated " : "Explicit ") << "Cast of:" << std::endl << indent+1;
-	arg->print(os, indent+1);
-	os << std::endl << indent << "... to:";
-	if ( result->isVoid() ) {
-		os << " nothing";
-	} else {
-		os << std::endl << indent+1;
-		result->print( os, indent+1 );
-	} // if
-	Expression::print( os, indent );
-}
-
-KeywordCastExpr::KeywordCastExpr( Expression * arg, AggregateDecl::Aggregate target ) : Expression(), arg(arg), target( target ) {}
-KeywordCastExpr::KeywordCastExpr( Expression * arg, AggregateDecl::Aggregate target, const KeywordCastExpr::Concrete & concrete_target ) : Expression(), arg(arg), target( target ), concrete_target(concrete_target) {}
-
-KeywordCastExpr::KeywordCastExpr( const KeywordCastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), target( other.target ) {}
-
-KeywordCastExpr::~KeywordCastExpr() {
-	delete arg;
-}
-
-const char * KeywordCastExpr::targetString() const {
-	return AggregateDecl::aggrString( target );
-}
-
-void KeywordCastExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Keyword Cast of:" << std::endl << indent+1;
-	arg->print(os, indent+1);
-	os << std::endl << indent << "... to: ";
-	os << targetString();
-	Expression::print( os, indent );
-}
-
-VirtualCastExpr::VirtualCastExpr( Expression * arg_, Type * toType ) : Expression(), arg(arg_) {
-	set_result(toType);
-}
-
-VirtualCastExpr::VirtualCastExpr( const VirtualCastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ) {
-}
-
-VirtualCastExpr::~VirtualCastExpr() {
-	delete arg;
-}
-
-void VirtualCastExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Virtual Cast of:" << std::endl << indent+1;
-	arg->print(os, indent+1);
-	os << std::endl << indent << "... to:";
-	if ( ! result ) {
-		os << " unknown";
-	} else {
-		os << std::endl << indent+1;
-		result->print( os, indent+1 );
-	} // if
-	Expression::print( os, indent );
-}
-
-UntypedMemberExpr::UntypedMemberExpr( Expression * member, Expression * aggregate ) :
-		Expression(), member(member), aggregate(aggregate) {
-	assert( aggregate );
-}
-
-UntypedMemberExpr::UntypedMemberExpr( const UntypedMemberExpr & other ) :
-		Expression( other ), member( maybeClone( other.member ) ), aggregate( maybeClone( other.aggregate ) ) {
-}
-
-UntypedMemberExpr::~UntypedMemberExpr() {
-	delete aggregate;
-	delete member;
-}
-
-bool UntypedMemberExpr::get_lvalue() const {
-	return aggregate->get_lvalue();
-}
-
-void UntypedMemberExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Untyped Member Expression, with field: " << std::endl << indent+1;
-	member->print(os, indent+1 );
-	os << indent << "... from aggregate:" << std::endl << indent+1;
-	aggregate->print(os, indent+1);
-	Expression::print( os, indent );
-}
-
-MemberExpr::MemberExpr( DeclarationWithType * member, Expression * aggregate ) :
-		Expression(), member(member), aggregate(aggregate) {
-	assert( member );
-	assert( aggregate );
-	assert( aggregate->result );
-
-	TypeSubstitution sub = aggregate->result->genericSubstitution();
-	Type * res = member->get_type()->clone();
-	sub.apply( res );
-	result = res;
-	result->get_qualifiers() |= aggregate->result->get_qualifiers();
-}
-
-MemberExpr::MemberExpr( const MemberExpr & other ) :
-		Expression( other ), member( other.member ), aggregate( maybeClone( other.aggregate ) ) {
-}
-
-MemberExpr::~MemberExpr() {
-	// don't delete the member declaration, since it points somewhere else in the tree
-	delete aggregate;
-}
-
-bool MemberExpr::get_lvalue() const {
-	// This is actually wrong by C, but it works with our current set-up.
-	return true;
-}
-
-void MemberExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Member Expression, with field:" << std::endl;
-	os << indent+1;
-	member->print( os, indent+1 );
-	os << std::endl << indent << "... from aggregate:" << std::endl << indent+1;
-	aggregate->print(os, indent + 1);
-	Expression::print( os, indent );
-}
-
-UntypedExpr::UntypedExpr( Expression * function, const std::list<Expression *> & args ) :
-		Expression(), function(function), args(args) {}
-
-UntypedExpr::UntypedExpr( const UntypedExpr & other ) :
-		Expression( other ), function( maybeClone( other.function ) ) {
-	cloneAll( other.args, args );
-}
-
-UntypedExpr::~UntypedExpr() {
-	delete function;
-	deleteAll( args );
-}
-
-UntypedExpr * UntypedExpr::createDeref( Expression * expr ) {
-	UntypedExpr * ret = new UntypedExpr( new NameExpr("*?"), std::list< Expression * >{ expr } );
-	if ( Type * type = expr->get_result() ) {
-		Type * base = InitTweak::getPointerBase( type );
-		assertf( base, "expected pointer type in dereference (type was %s)", toString( type ).c_str() );
-		ret->set_result( base->clone() );
-		if ( GenPoly::referencesPermissable() ) {
-			// if references are still allowed in the AST, dereference returns a reference
-			ret->set_result( new ReferenceType( Type::Qualifiers(), ret->get_result() ) );
-		}
-	}
-	return ret;
-}
-
-UntypedExpr * UntypedExpr::createAssign( Expression * arg1, Expression * arg2 ) {
-	assert( arg1 && arg2 );
-	UntypedExpr * ret = new UntypedExpr( new NameExpr( "?=?" ), std::list< Expression * >{ arg1, arg2 } );
-	if ( arg1->get_result() && arg2->get_result() ) {
-		// if both expressions are typed, assumes that this assignment is a C bitwise assignment,
-		// so the result is the type of the RHS
-		ret->set_result( arg2->get_result()->clone() );
-	}
-	return ret;
-}
-
-bool UntypedExpr::get_lvalue() const {
-	// from src/GenPoly/Lvalue.cc: isIntrinsicReference
-	static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
-	std::string fname = InitTweak::getFunctionName( const_cast< UntypedExpr * >( this ) );
-	return lvalueFunctions.count(fname);
-}
-
-void UntypedExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Applying untyped:" << std::endl;
-	os << indent+1;
-	function->print(os, indent+1);
-	os << std::endl << indent << "...to:" << std::endl;
-	printAll(args, os, indent+1);
-	Expression::print( os, indent );
-}
-
-NameExpr::NameExpr( std::string name ) : Expression(), name(name) {
-	assertf(name != "0", "Zero is not a valid name");
-	assertf(name != "1", "One is not a valid name");
-}
-
-NameExpr::NameExpr( const NameExpr & other ) : Expression( other ), name( other.name ) {
-}
-
-NameExpr::~NameExpr() {}
-
-void NameExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Name: " << get_name();
-	Expression::print( os, indent );
-}
-
-LogicalExpr::LogicalExpr( Expression * arg1_, Expression * arg2_, bool andp ) :
-		Expression(), arg1(arg1_), arg2(arg2_), isAnd(andp) {
-	set_result( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
-}
-
-LogicalExpr::LogicalExpr( const LogicalExpr & other ) :
-		Expression( other ), arg1( maybeClone( other.arg1 ) ), arg2( maybeClone( other.arg2 ) ), isAnd( other.isAnd ) {
-}
-
-LogicalExpr::~LogicalExpr() {
-	delete arg1;
-	delete arg2;
-}
-
-void LogicalExpr::print( std::ostream & os, Indenter indent )const {
-	os << "Short-circuited operation (" << (isAnd ? "and" : "or") << ") on: ";
-	arg1->print(os);
-	os << " and ";
-	arg2->print(os);
-	Expression::print( os, indent );
-}
-
-ConditionalExpr::ConditionalExpr( Expression * arg1, Expression * arg2, Expression * arg3 ) :
-		Expression(), arg1(arg1), arg2(arg2), arg3(arg3) {}
-
-ConditionalExpr::ConditionalExpr( const ConditionalExpr & other ) :
-		Expression( other ), arg1( maybeClone( other.arg1 ) ), arg2( maybeClone( other.arg2 ) ), arg3( maybeClone( other.arg3 ) ) {
-}
-
-ConditionalExpr::~ConditionalExpr() {
-	delete arg1;
-	delete arg2;
-	delete arg3;
-}
-
-bool ConditionalExpr::get_lvalue() const {
-	return false;
-}
-
-void ConditionalExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Conditional expression on: " << std::endl << indent+1;
-	arg1->print( os, indent+1 );
-	os << indent << "First alternative:" << std::endl << indent+1;
-	arg2->print( os, indent+1 );
-	os << indent << "Second alternative:" << std::endl << indent+1;
-	arg3->print( os, indent+1 );
-	Expression::print( os, indent );
-}
-
-AsmExpr::AsmExpr( const AsmExpr & other ) : Expression( other ), inout( other.inout ), constraint( maybeClone( other.constraint ) ), operand( maybeClone( other.operand ) ) {}
-
-
-void AsmExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Asm Expression: " << std::endl;
-	if ( !inout.empty() ) os <<  "[" << inout << "] ";
-	if ( constraint ) constraint->print( os, indent+1 );
-	if ( operand ) operand->print( os, indent+1 );
-}
-
-
-ImplicitCopyCtorExpr::ImplicitCopyCtorExpr( ApplicationExpr * callExpr ) : callExpr( callExpr ) {
-	assert( callExpr );
-	assert( callExpr->result );
-	set_result( callExpr->result->clone() );
-}
-
-ImplicitCopyCtorExpr::ImplicitCopyCtorExpr( const ImplicitCopyCtorExpr & other ) : Expression( other ), callExpr( maybeClone( other.callExpr ) ) {
-}
-
-ImplicitCopyCtorExpr::~ImplicitCopyCtorExpr() {
-	set_env( nullptr ); // ImplicitCopyCtorExpr does not take ownership of an environment
-	delete callExpr;
-}
-
-void ImplicitCopyCtorExpr::print( std::ostream & os, Indenter indent ) const {
-	os <<  "Implicit Copy Constructor Expression: " << std::endl << indent+1;
-	callExpr->print( os, indent+1 );
-}
-
-
-ConstructorExpr::ConstructorExpr( Expression * callExpr ) : callExpr( callExpr ) {
-	// allow resolver to type a constructor used as an expression as if it has the same type as its first argument
-	assert( callExpr );
-	Expression * arg = InitTweak::getCallArg( callExpr, 0 );
-	assert( arg );
-	set_result( maybeClone( arg->result ) );
-}
-
-ConstructorExpr::ConstructorExpr( const ConstructorExpr & other ) : Expression( other ), callExpr( maybeClone( other.callExpr ) ) {
-}
-
-ConstructorExpr::~ConstructorExpr() {
-	delete callExpr;
-}
-
-bool ConstructorExpr::get_lvalue() const {
-	return false;
-}
-
-void ConstructorExpr::print( std::ostream & os, Indenter indent ) const {
-	os <<  "Constructor Expression: " << std::endl << indent+1;
-	callExpr->print( os, indent + 2 );
-	Expression::print( os, indent );
-}
-
-
-CompoundLiteralExpr::CompoundLiteralExpr( Type * type, Initializer * initializer ) : initializer( initializer ) {
-	assert( type && initializer );
-	set_result( type );
-}
-
-CompoundLiteralExpr::CompoundLiteralExpr( const CompoundLiteralExpr & other ) : Expression( other ), initializer( other.initializer->clone() ) {}
-
-CompoundLiteralExpr::~CompoundLiteralExpr() {
-	delete initializer;
-}
-
-bool CompoundLiteralExpr::get_lvalue() const {
-	return true;
-}
-
-void CompoundLiteralExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Compound Literal Expression: " << std::endl << indent+1;
-	result->print( os, indent+1 );
-	os << indent+1;
-	initializer->print( os, indent+1 );
-	Expression::print( os, indent );
-}
-
-RangeExpr::RangeExpr( Expression * low, Expression * high ) : low( low ), high( high ) {}
-RangeExpr::RangeExpr( const RangeExpr & other ) : Expression( other ), low( other.low->clone() ), high( other.high->clone() ) {}
-void RangeExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Range Expression: ";
-	low->print( os, indent );
-	os << " ... ";
-	high->print( os, indent );
-	Expression::print( os, indent );
-}
-
-StmtExpr::StmtExpr( CompoundStmt * statements ) : statements( statements ) {
-	computeResult();
-}
-StmtExpr::StmtExpr( const StmtExpr & other ) : Expression( other ), statements( other.statements->clone() ), resultExpr( other.resultExpr ) {
-	cloneAll( other.returnDecls, returnDecls );
-	cloneAll( other.dtors, dtors );
-}
-StmtExpr::~StmtExpr() {
-	delete statements;
-	deleteAll( dtors );
-	deleteAll( returnDecls );
-}
-void StmtExpr::computeResult() {
-	assert( statements );
-	std::list< Statement * > & body = statements->kids;
-	delete result;
-	result = nullptr;
-	if ( ! returnDecls.empty() ) {
-		// prioritize return decl for result type, since if a return decl exists, then
-		// the StmtExpr is currently in an intermediate state where the body will always
-		// give a void result type.
-		result = returnDecls.front()->get_type()->clone();
-	} else if ( ! body.empty() ) {
-		if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( body.back() ) ) {
-			result = maybeClone( exprStmt->expr->result );
-		}
-	}
-	// ensure that StmtExpr has a result type
-	if ( ! result ) {
-		result = new VoidType( Type::Qualifiers() );
-	}
-}
-bool StmtExpr::get_lvalue() const {
-	return false;
-}
-void StmtExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Statement Expression: " << std::endl << indent+1;
-	statements->print( os, indent+1 );
-	if ( ! returnDecls.empty() ) {
-		os << indent+1 << "... with returnDecls: ";
-		printAll( returnDecls, os, indent+1 );
-	}
-	if ( ! dtors.empty() ) {
-		os << indent+1 << "... with dtors: ";
-		printAll( dtors, os, indent+1 );
-	}
-	Expression::print( os, indent );
-}
-
-
-long long UniqueExpr::count = 0;
-UniqueExpr::UniqueExpr( Expression * expr, long long idVal ) : expr( expr ), object( nullptr ), var( nullptr ), id( idVal ) {
-	assert( expr );
-	assert( count != -1 );
-	if ( id == -1 ) id = count++;
-	if ( expr->get_result() ) {
-		set_result( expr->get_result()->clone() );
-	}
-}
-UniqueExpr::UniqueExpr( const UniqueExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ), object( maybeClone( other.object ) ), var( maybeClone( other.var ) ), id( other.id ) {
-}
-UniqueExpr::~UniqueExpr() {
-	delete expr;
-	delete object;
-	delete var;
-}
-void UniqueExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Unique Expression with id:" << id << std::endl << indent+1;
-	expr->print( os, indent+1 );
-	if ( object ) {
-		os << indent << "... with decl: ";
-		get_object()->printShort( os, indent+1 );
-	}
-	Expression::print( os, indent );
-}
-
-InitAlternative::InitAlternative( Type * type, Designation * designation ) : type( type ), designation( designation ) {}
-InitAlternative::InitAlternative( const InitAlternative & other ) : type( maybeClone( other.type ) ), designation( maybeClone( other.designation ) ) {}
-InitAlternative::~InitAlternative() {
-	delete type;
-	delete designation;
-}
-
-UntypedInitExpr::UntypedInitExpr( Expression * expr, const std::list<InitAlternative> & initAlts ) : expr( expr ), initAlts( initAlts ) {}
-UntypedInitExpr::UntypedInitExpr( const UntypedInitExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ), initAlts( other.initAlts ) {}
-UntypedInitExpr::~UntypedInitExpr() {
-	delete expr;
-}
-
-void UntypedInitExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Untyped Init Expression" << std::endl << indent+1;
-	expr->print( os, indent+1 );
-	if ( ! initAlts.empty() ) {
-		for ( const InitAlternative & alt : initAlts ) {
-			os << indent+1 <<  "InitAlternative: ";
-			alt.type->print( os, indent+1 );
-			alt.designation->print( os, indent+1 );
-		}
-	}
-}
-
-InitExpr::InitExpr( Expression * expr, Designation * designation ) : expr( expr ), designation( designation ) {
-	set_result( expr->get_result()->clone() );
-}
-InitExpr::InitExpr( const InitExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ), designation( maybeClone( other.designation) ) {}
-InitExpr::~InitExpr() {
-	delete expr;
-	delete designation;
-}
-
-void InitExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Init Expression" << std::endl << indent+1;
-	expr->print( os, indent+1 );
-	os << indent+1 << "... with designation: ";
-	designation->print( os, indent+1 );
-}
-
-DeletedExpr::DeletedExpr( Expression * expr, Declaration * deleteStmt ) : expr( expr ), deleteStmt( deleteStmt ) {
-	assert( expr->result );
-	result = expr->result->clone();
-}
-DeletedExpr::DeletedExpr( const DeletedExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ), deleteStmt( other.deleteStmt ) {}
-DeletedExpr::~DeletedExpr() {
-	delete expr;
-}
-
-void DeletedExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Deleted Expression" << std::endl << indent+1;
-	expr->print( os, indent+1 );
-	os << std::endl << indent+1 << "... deleted by: ";
-	deleteStmt->print( os, indent+1 );
-}
-
-
-DefaultArgExpr::DefaultArgExpr( Expression * expr ) : expr( expr ) {
-	assert( expr->result );
-	result = expr->result->clone();
-}
-DefaultArgExpr::DefaultArgExpr( const DefaultArgExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ) {}
-DefaultArgExpr::~DefaultArgExpr() {
-	delete expr;
-}
-
-void DefaultArgExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Default Argument Expression" << std::endl << indent+1;
-	expr->print( os, indent+1 );
-}
-
-GenericExpr::Association::Association( Type * type, Expression * expr ) : type( type ), expr( expr ), isDefault( false ) {}
-GenericExpr::Association::Association( Expression * expr ) : type( nullptr ), expr( expr ), isDefault( true ) {}
-GenericExpr::Association::Association( const Association & other ) : type( maybeClone( other.type ) ), expr( maybeClone( other.expr ) ), isDefault( other.isDefault ) {}
-GenericExpr::Association::~Association() {
-	delete type;
-	delete expr;
-}
-
-GenericExpr::GenericExpr( Expression * control, const std::list<Association> & assoc ) : Expression(), control( control ), associations( assoc ) {}
-GenericExpr::GenericExpr( const GenericExpr & other ) : Expression(other), control( maybeClone( other.control ) ), associations( other.associations ) {
-}
-GenericExpr::~GenericExpr() {
-	delete control;
-}
-
-void GenericExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "C11 _Generic Expression" << std::endl << indent+1;
-	control->print( os, indent+1 );
-	os << std::endl << indent+1 << "... with associations: " << std::endl;
-	for ( const Association & assoc : associations ) {
-		os << indent+1;
-		if (assoc.isDefault) {
-			os << "... default: ";
-			assoc.expr->print( os, indent+1 );
-		} else {
-			os << "... type: ";
-			assoc.type->print( os, indent+1 );
-			os << std::endl << indent+1 << "... expression: ";
-			assoc.expr->print( os, indent+1 );
-			os << std::endl;
-		}
-		os << std::endl;
-	}
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,1011 +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.
-//
-// Expression.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Dec 11 16:50:19 2019
-// Update Count     : 60
-//
-
-#pragma once
-
-#include <iosfwd>                 // for ostream
-#include <list>                   // for list, list<>::iterator
-#include <map>                    // for map, map<>::value_compare
-#include <memory>                 // for allocator, unique_ptr
-#include <string>                 // for string
-#include <vector>                 // for vector
-
-#include "BaseSyntaxNode.h"       // for BaseSyntaxNode
-#include "Constant.h"             // for Constant
-#include "Initializer.h"          // for Designation (ptr only), Initializer
-#include "Label.h"                // for Label
-#include "Mutator.h"              // for Mutator
-#include "Declaration.h"          // for Aggregate
-#include "SynTree.h"              // for UniqueId
-#include "Visitor.h"              // for Visitor
-
-
-struct ParamEntry;
-
-typedef std::map< UniqueId, ParamEntry > InferredParams;
-
-/// ParamEntry contains the i.d. of a declaration and a type that is derived from that declaration,
-/// but subject to decay-to-pointer and type parameter renaming
-struct ParamEntry {
-	ParamEntry(): decl( 0 ), declptr( nullptr ), actualType( nullptr ), formalType( nullptr ), expr( nullptr ) {}
-	ParamEntry( UniqueId decl, Declaration * declptr, Type * actualType, Type * formalType, Expression* expr );
-	ParamEntry( const ParamEntry & other );
-	ParamEntry( ParamEntry && other );
-	~ParamEntry();
-	ParamEntry & operator=( ParamEntry && other );
-
-	UniqueId const decl;
-	Declaration * const declptr;
-	Type * const actualType;
-	Type * const formalType;
-	Expression * expr;
-};
-
-/// Expression is the root type for all expressions
-class Expression : public BaseSyntaxNode {
-  public:
-	Type * result;
-	TypeSubstitution * env;
-	bool extension = false;
-	InferredParams inferParams;       ///< Post-resolution inferred parameter slots
-	std::vector<UniqueId> resnSlots;  ///< Pre-resolution inferred parameter slots
-
-	// xxx - should turn inferParams+resnSlots into a union to save some memory
-
-	Expression();
-	Expression( const Expression & other );
-	virtual ~Expression();
-
-	Type *& get_result() { return result; }
-	const Type * get_result() const { return result; }
-	void set_result( Type * newValue ) { result = newValue; }
-	virtual bool get_lvalue() const;
-
-	TypeSubstitution * get_env() const { return env; }
-	void set_env( TypeSubstitution * newValue ) { env = newValue; }
-	bool get_extension() const { return extension; }
-	Expression * set_extension( bool exten ) { extension = exten; return this; }
-
-	// move other's inferParams to this
-	void spliceInferParams( Expression * other );
-
-	virtual Expression * clone() const override = 0;
-	virtual void accept( Visitor & v ) override = 0;
-	virtual void accept( Visitor & v ) const override = 0;
-	virtual Expression * acceptMutator( Mutator & m ) override = 0;
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// ApplicationExpr represents the application of a function to a set of parameters.  This is the result of running an
-/// UntypedExpr through the expression analyzer.
-class ApplicationExpr : public Expression {
-  public:
-	Expression * function;
-	std::list<Expression *> args;
-
-	ApplicationExpr( Expression * function, const std::list<Expression *> & args = std::list< Expression * >() );
-	ApplicationExpr( const ApplicationExpr & other );
-	virtual ~ApplicationExpr();
-
-	bool get_lvalue() const final;
-
-	Expression * get_function() const { return function; }
-	void set_function( Expression * newValue ) { function = newValue; }
-	std::list<Expression *>& get_args() { return args; }
-
-	virtual ApplicationExpr * clone() const override { return new ApplicationExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// UntypedExpr represents the application of a function to a set of parameters, but where the particular overload for
-/// the function name has not yet been determined.  Most operators are converted into functional form automatically, to
-/// permit operator overloading.
-class UntypedExpr : public Expression {
-  public:
-	Expression * function;
-	std::list<Expression*> args;
-
-	UntypedExpr( Expression * function, const std::list<Expression *> & args = std::list< Expression * >() );
-	UntypedExpr( const UntypedExpr & other );
-	virtual ~UntypedExpr();
-
-	bool get_lvalue() const final;
-
-	Expression * get_function() const { return function; }
-	void set_function( Expression * newValue ) { function = newValue; }
-
-	std::list<Expression*>::iterator begin_args() { return args.begin(); }
-	std::list<Expression*>::iterator end_args() { return args.end(); }
-	std::list<Expression*>& get_args() { return args; }
-
-	static UntypedExpr * createDeref( Expression * arg );
-	static UntypedExpr * createAssign( Expression * arg1, Expression * arg2 );
-
-	virtual UntypedExpr * clone() const override { return new UntypedExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// NameExpr contains a name whose meaning is still not determined
-class NameExpr : public Expression {
-  public:
-	std::string name;
-
-	NameExpr( std::string name );
-	NameExpr( const NameExpr & other );
-	virtual ~NameExpr();
-
-	const std::string & get_name() const { return name; }
-	void set_name( std::string newValue ) { name = newValue; }
-
-	virtual NameExpr * clone() const override { return new NameExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-// [Qualifier].name; Qualifier is the type_name from the parser
-class QualifiedNameExpr : public Expression {
-  public:
-	Declaration * type_decl;
-	std::string name;
-
-	QualifiedNameExpr( Declaration * decl, std::string name): Expression(), type_decl(decl), name(name) {}
-	QualifiedNameExpr( const QualifiedNameExpr & other): Expression(other), type_decl(other.type_decl), name(other.name) {}
-
-	virtual ~QualifiedNameExpr() {
-		delete type_decl;
-	}
-
-	virtual QualifiedNameExpr * clone() const override {
-		return new QualifiedNameExpr( * this );
-	}
-	virtual void accept( Visitor & v ) override { v.visit(this); }
-	virtual void accept( Visitor & v ) const override { v.visit(this); }
-	virtual Expression * acceptMutator( Mutator & m ) override { 
-		return m.mutate( this ); 
-	}
-	
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override {
-		type_decl->print( os, indent );
-		os << name << std::endl;
-	}
-};
-
-/// VariableExpr represents an expression that simply refers to the value of a named variable.
-/// Does not take ownership of var.
-class VariableExpr : public Expression {
-  public:
-	DeclarationWithType * var;
-
-	VariableExpr();
-	VariableExpr( DeclarationWithType * var );
-	VariableExpr( const VariableExpr & other );
-	virtual ~VariableExpr();
-
-	bool get_lvalue() const final;
-
-	DeclarationWithType * get_var() const { return var; }
-	void set_var( DeclarationWithType * newValue ) { var = newValue; }
-
-	static VariableExpr * functionPointer( FunctionDecl * decl );
-
-	virtual VariableExpr * clone() const override { return new VariableExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-// The following classes are used to represent expression types that cannot be converted into
-// function-call format.
-
-/// AddressExpr represents a address-of expression, e.g. & e
-class AddressExpr : public Expression {
-  public:
-	Expression * arg;
-
-	AddressExpr( Expression * arg );
-	AddressExpr( const AddressExpr & other );
-	virtual ~AddressExpr();
-
-	Expression * get_arg() const { return arg; }
-	void set_arg(Expression * newValue ) { arg = newValue; }
-
-	virtual AddressExpr * clone() const override { return new AddressExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-// GCC &&label
-// https://gcc.gnu.org/onlinedocs/gcc-3.4.2/gcc/Labels-as-Values.html
-class LabelAddressExpr : public Expression {
-  public:
-	Label arg;
-
-	LabelAddressExpr( const Label &arg );
-	LabelAddressExpr( const LabelAddressExpr & other );
-	virtual ~LabelAddressExpr();
-
-	virtual LabelAddressExpr * clone() const override { return new LabelAddressExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// CastExpr represents a type cast expression, e.g. (int)e
-class CastExpr : public Expression {
-  public:
-	Expression * arg;
-
-	// Inidicates cast is introduced by the CFA type system.
-	// true for casts that the resolver introduces to force a return type
-	// false for casts from user code
-	// false for casts from desugaring advanced CFA features into simpler CFA
-	// example
-	//   int * p;     // declaration
-	//   (float *) p; // use, with subject cast
-	// subject cast isGenerated means we are considering an interpretation with a type mismatch
-	// subject cast not isGenerated means someone in charge wants it that way
-	bool isGenerated = true;
-
-	enum CastKind {
-		Default, // C
-		Coerce, // reinterpret cast
-		Return  // overload selection
-	};
-
-	CastKind kind = Default;
-
-	CastExpr( Expression * arg, bool isGenerated = true, CastKind kind = Default );
-	CastExpr( Expression * arg, Type * toType, bool isGenerated = true, CastKind kind = Default );
-	CastExpr( Expression * arg, void * ) = delete; // prevent accidentally passing pointers for isGenerated in the first constructor
-	CastExpr( const CastExpr & other );
-	virtual ~CastExpr();
-
-	bool get_lvalue() const final;
-
-	Expression * get_arg() const { return arg; }
-	void set_arg( Expression * newValue ) { arg = newValue; }
-
-	virtual CastExpr * clone() const override { return new CastExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// KeywordCastExpr represents a cast to 'keyword types', e.g. (thread &)t
-class KeywordCastExpr : public Expression {
-public:
-	Expression * arg;
-	struct Concrete {
-		std::string field;
-		std::string getter;
-	};
-	AggregateDecl::Aggregate target;
-	Concrete concrete_target;
-
-	KeywordCastExpr( Expression * arg, AggregateDecl::Aggregate target );
-	KeywordCastExpr( Expression * arg, AggregateDecl::Aggregate target, const Concrete & concrete_target );
-	KeywordCastExpr( const KeywordCastExpr & other );
-	virtual ~KeywordCastExpr();
-
-	const char * targetString() const;
-
-	virtual KeywordCastExpr * clone() const override { return new KeywordCastExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// VirtualCastExpr repersents a virtual dynamic cast, e.g. (virtual exception)e
-class VirtualCastExpr : public Expression {
-  public:
-	Expression * arg;
-
-	VirtualCastExpr( Expression * arg, Type * toType );
-	VirtualCastExpr( const VirtualCastExpr & other );
-	virtual ~VirtualCastExpr();
-
-	Expression * get_arg() const { return arg; }
-	void set_arg( Expression * newValue ) { arg = newValue; }
-
-	virtual VirtualCastExpr * clone() const override { return new VirtualCastExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// UntypedMemberExpr represents a member selection operation, e.g. q.p before processing by the expression analyzer
-class UntypedMemberExpr : public Expression {
-  public:
-	Expression * member;
-	Expression * aggregate;
-
-	UntypedMemberExpr( Expression * member, Expression * aggregate );
-	UntypedMemberExpr( const UntypedMemberExpr & other );
-	virtual ~UntypedMemberExpr();
-
-	bool get_lvalue() const final;
-
-	Expression * get_member() const { return member; }
-	void set_member( Expression * newValue ) { member = newValue; }
-	Expression * get_aggregate() const { return aggregate; }
-	void set_aggregate( Expression * newValue ) { aggregate = newValue; }
-
-	virtual UntypedMemberExpr * clone() const override { return new UntypedMemberExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// MemberExpr represents a member selection operation, e.g. q.p after processing by the expression analyzer.
-/// Does not take ownership of member.
-class MemberExpr : public Expression {
-  public:
-	DeclarationWithType * member;
-	Expression * aggregate;
-
-	MemberExpr( DeclarationWithType * member, Expression * aggregate );
-	MemberExpr( const MemberExpr & other );
-	virtual ~MemberExpr();
-
-	bool get_lvalue() const final;
-
-	DeclarationWithType * get_member() const { return member; }
-	void set_member( DeclarationWithType * newValue ) { member = newValue; }
-	Expression * get_aggregate() const { return aggregate; }
-	void set_aggregate( Expression * newValue ) { aggregate = newValue; }
-
-	virtual MemberExpr * clone() const override { return new MemberExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// ConstantExpr represents an expression that simply refers to the value of a constant
-class ConstantExpr : public Expression {
-  public:
-	Constant constant;
-
-	ConstantExpr( Constant constant );
-	ConstantExpr( const ConstantExpr & other );
-	virtual ~ConstantExpr();
-
-	Constant * get_constant() { return & constant; }
-	const Constant * get_constant() const { return & constant; }
-	void set_constant( const Constant & newValue ) { constant = newValue; }
-
-	long long int intValue() const;
-
-	virtual ConstantExpr * clone() const override { return new ConstantExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// SizeofExpr represents a sizeof expression (could be sizeof(int) or sizeof 3+4)
-class SizeofExpr : public Expression {
-  public:
-	Expression * expr;
-	Type * type;
-	bool isType;
-
-	SizeofExpr( Expression * expr );
-	SizeofExpr( const SizeofExpr & other );
-	SizeofExpr( Type * type );
-	virtual ~SizeofExpr();
-
-	Expression * get_expr() const { return expr; }
-	void set_expr( Expression * newValue ) { expr = newValue; }
-	Type * get_type() const { return type; }
-	void set_type( Type * newValue ) { type = newValue; }
-	bool get_isType() const { return isType; }
-	void set_isType( bool newValue ) { isType = newValue; }
-
-	virtual SizeofExpr * clone() const override { return new SizeofExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// AlignofExpr represents an alignof expression
-class AlignofExpr : public Expression {
-  public:
-	Expression * expr;
-	Type * type;
-	bool isType;
-
-	AlignofExpr( Expression * expr );
-	AlignofExpr( const AlignofExpr & other );
-	AlignofExpr( Type * type );
-	virtual ~AlignofExpr();
-
-	Expression * get_expr() const { return expr; }
-	void set_expr( Expression * newValue ) { expr = newValue; }
-	Type * get_type() const { return type; }
-	void set_type( Type * newValue ) { type = newValue; }
-	bool get_isType() const { return isType; }
-	void set_isType( bool newValue ) { isType = newValue; }
-
-	virtual AlignofExpr * clone() const override { return new AlignofExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// UntypedOffsetofExpr represents an offsetof expression before resolution
-class UntypedOffsetofExpr : public Expression {
-  public:
-	Type * type;
-	std::string member;
-
-	UntypedOffsetofExpr( Type * type, const std::string & member );
-	UntypedOffsetofExpr( const UntypedOffsetofExpr & other );
-	virtual ~UntypedOffsetofExpr();
-
-	std::string get_member() const { return member; }
-	void set_member( const std::string & newValue ) { member = newValue; }
-	Type * get_type() const { return type; }
-	void set_type( Type * newValue ) { type = newValue; }
-
-	virtual UntypedOffsetofExpr * clone() const override { return new UntypedOffsetofExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// OffsetofExpr represents an offsetof expression
-class OffsetofExpr : public Expression {
-  public:
-	Type * type;
-	DeclarationWithType * member;
-
-	OffsetofExpr( Type * type, DeclarationWithType * member );
-	OffsetofExpr( const OffsetofExpr & other );
-	virtual ~OffsetofExpr();
-
-	Type * get_type() const { return type; }
-	void set_type( Type * newValue ) { type = newValue; }
-	DeclarationWithType * get_member() const { return member; }
-	void set_member( DeclarationWithType * newValue ) { member = newValue; }
-
-	virtual OffsetofExpr * clone() const override { return new OffsetofExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// Expression representing a pack of field-offsets for a generic type
-class OffsetPackExpr : public Expression {
-public:
-	StructInstType * type;
-
-	OffsetPackExpr( StructInstType * type );
-	OffsetPackExpr( const OffsetPackExpr & other );
-	virtual ~OffsetPackExpr();
-
-	StructInstType * get_type() const { return type; }
-	void set_type( StructInstType * newValue ) { type = newValue; }
-
-	virtual OffsetPackExpr * clone() const override { return new OffsetPackExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// LogicalExpr represents a short-circuit boolean expression (&& or ||)
-class LogicalExpr : public Expression {
-  public:
-	Expression * arg1;
-	Expression * arg2;
-
-	LogicalExpr( Expression * arg1, Expression * arg2, bool andp = true );
-	LogicalExpr( const LogicalExpr & other );
-	virtual ~LogicalExpr();
-
-	bool get_isAnd() const { return isAnd; }
-	Expression * get_arg1() { return arg1; }
-	void set_arg1( Expression * newValue ) { arg1 = newValue; }
-	Expression * get_arg2() const { return arg2; }
-	void set_arg2( Expression * newValue ) { arg2 = newValue; }
-
-	virtual LogicalExpr * clone() const override { return new LogicalExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-
-  private:
-	bool isAnd;
-};
-
-/// ConditionalExpr represents the three-argument conditional ( p ? a : b )
-class ConditionalExpr : public Expression {
-  public:
-	Expression * arg1;
-	Expression * arg2;
-	Expression * arg3;
-
-	ConditionalExpr( Expression * arg1, Expression * arg2, Expression * arg3 );
-	ConditionalExpr( const ConditionalExpr & other );
-	virtual ~ConditionalExpr();
-
-	bool get_lvalue() const final;
-
-	Expression * get_arg1() const { return arg1; }
-	void set_arg1( Expression * newValue ) { arg1 = newValue; }
-	Expression * get_arg2() const { return arg2; }
-	void set_arg2( Expression * newValue ) { arg2 = newValue; }
-	Expression * get_arg3() const { return arg3; }
-	void set_arg3( Expression * newValue ) { arg3 = newValue; }
-
-	virtual ConditionalExpr * clone() const override { return new ConditionalExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// CommaExpr represents the sequence operator ( a, b )
-class CommaExpr : public Expression {
-  public:
-	Expression * arg1;
-	Expression * arg2;
-
-	CommaExpr( Expression * arg1, Expression * arg2 );
-	CommaExpr( const CommaExpr & other );
-	virtual ~CommaExpr();
-
-	bool get_lvalue() const final;
-
-	Expression * get_arg1() const { return arg1; }
-	void set_arg1( Expression * newValue ) { arg1 = newValue; }
-	Expression * get_arg2() const { return arg2; }
-	void set_arg2( Expression * newValue ) { arg2 = newValue; }
-
-	virtual CommaExpr * clone() const override { return new CommaExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// TypeExpr represents a type used in an expression (e.g. as a type generator parameter)
-class TypeExpr : public Expression {
-  public:
-	Type * type;
-
-	TypeExpr( Type * type );
-	TypeExpr( const TypeExpr & other );
-	virtual ~TypeExpr();
-
-	Type * get_type() const { return type; }
-	void set_type( Type * newValue ) { type = newValue; }
-
-	virtual TypeExpr * clone() const override { return new TypeExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// DimensionExpr represents a type-system provided value used in an expression ( forrall([N]) ... N + 1 )
-class DimensionExpr : public Expression {
-  public:
-	std::string name;
-
-	DimensionExpr( std::string name );
-	DimensionExpr( const DimensionExpr & other );
-	virtual ~DimensionExpr();
-
-	const std::string & get_name() const { return name; }
-	void set_name( std::string newValue ) { name = newValue; }
-
-	virtual DimensionExpr * clone() const override { return new DimensionExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// AsmExpr represents a GCC 'asm constraint operand' used in an asm statement: [output] "=f" (result)
-class AsmExpr : public Expression {
-  public:
-	std::string inout;
-	Expression * constraint;
-	Expression * operand;
-
-	AsmExpr( const std::string * _inout, Expression * constraint, Expression * operand ) : inout( _inout ? *_inout : "" ), constraint( constraint ), operand( operand ) { delete _inout; }
-	AsmExpr( const AsmExpr & other );
-	virtual ~AsmExpr() { delete constraint; delete operand; };
-
-	virtual AsmExpr * clone() const override { return new AsmExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-
-	// https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Machine-Constraints.html#Machine-Constraints
-};
-
-/// ImplicitCopyCtorExpr represents the application of a function to a set of parameters,
-/// along with a set of copy constructor calls, one for each argument.
-class ImplicitCopyCtorExpr : public Expression {
-public:
-	ApplicationExpr * callExpr = nullptr;
-
-	ImplicitCopyCtorExpr( ApplicationExpr * callExpr );
-	ImplicitCopyCtorExpr( const ImplicitCopyCtorExpr & other );
-	virtual ~ImplicitCopyCtorExpr();
-
-	virtual ImplicitCopyCtorExpr * clone() const override { return new ImplicitCopyCtorExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// ConstructorExpr represents the use of a constructor in an expression context, e.g. int * x = malloc() { 5 };
-class ConstructorExpr : public Expression {
-public:
-	Expression * callExpr;
-
-	ConstructorExpr( Expression * callExpr );
-	ConstructorExpr( const ConstructorExpr & other );
-	~ConstructorExpr();
-
-	bool get_lvalue() const final;
-
-	Expression * get_callExpr() const { return callExpr; }
-	void set_callExpr( Expression * newValue ) { callExpr = newValue; }
-
-	virtual ConstructorExpr * clone() const override { return new ConstructorExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// CompoundLiteralExpr represents a C99 'compound literal'
-class CompoundLiteralExpr : public Expression {
-  public:
-	Initializer * initializer;
-
-	CompoundLiteralExpr( Type * type, Initializer * initializer );
-	CompoundLiteralExpr( const CompoundLiteralExpr & other );
-	virtual ~CompoundLiteralExpr();
-
-	bool get_lvalue() const final;
-
-	Initializer * get_initializer() const { return initializer; }
-	void set_initializer( Initializer * i ) { initializer = i; }
-
-	virtual CompoundLiteralExpr * clone() const override { return new CompoundLiteralExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// RangeExpr represents a range e.g. '3 ... 5' or '1~10'
-class RangeExpr : public Expression {
-  public:
-	Expression * low, * high;
-
-	RangeExpr( Expression * low, Expression * high );
-	RangeExpr( const RangeExpr & other );
-
-	Expression * get_low() const { return low; }
-	Expression * get_high() const { return high; }
-	RangeExpr * set_low( Expression * low ) { RangeExpr::low = low; return this; }
-	RangeExpr * set_high( Expression * high ) { RangeExpr::high = high; return this; }
-
-	virtual RangeExpr * clone() const override { return new RangeExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// UntypedTupleExpr represents a tuple expression ( [a, b, c] ) before resolution
-class UntypedTupleExpr : public Expression {
-  public:
-	std::list<Expression*> exprs;
-
-	UntypedTupleExpr( const std::list< Expression * > & exprs );
-	UntypedTupleExpr( const UntypedTupleExpr & other );
-	virtual ~UntypedTupleExpr();
-
-	std::list<Expression*>& get_exprs() { return exprs; }
-
-	virtual UntypedTupleExpr * clone() const override { return new UntypedTupleExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// TupleExpr represents a tuple expression ( [a, b, c] )
-class TupleExpr : public Expression {
-  public:
-	std::list<Expression*> exprs;
-
-	TupleExpr( const std::list< Expression * > & exprs );
-	TupleExpr( const TupleExpr & other );
-	virtual ~TupleExpr();
-
-	bool get_lvalue() const final;
-
-	std::list<Expression*>& get_exprs() { return exprs; }
-
-	virtual TupleExpr * clone() const override { return new TupleExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// TupleIndexExpr represents an element selection operation on a tuple value, e.g. t.3 after processing by the expression analyzer
-class TupleIndexExpr : public Expression {
-  public:
-	Expression * tuple;
-	unsigned int index;
-
-	TupleIndexExpr( Expression * tuple, unsigned int index );
-	TupleIndexExpr( const TupleIndexExpr & other );
-	virtual ~TupleIndexExpr();
-
-	bool get_lvalue() const final;
-
-	Expression * get_tuple() const { return tuple; }
-	int get_index() const { return index; }
-	TupleIndexExpr * set_tuple( Expression * newValue ) { tuple = newValue; return this; }
-	TupleIndexExpr * set_index( unsigned int newValue ) { index = newValue; return this; }
-
-	virtual TupleIndexExpr * clone() const override { return new TupleIndexExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// TupleAssignExpr represents a multiple assignment operation, where both sides of the assignment have tuple type, e.g. [a, b, c] = [d, e, f];, a mass assignment operation, where the left hand side has tuple type and the right hand side does not, e.g. [a, b, c] = 5.0;, or a tuple ctor/dtor expression
-class TupleAssignExpr : public Expression {
-  public:
-	StmtExpr * stmtExpr = nullptr;
-
-	TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls );
-	TupleAssignExpr( const TupleAssignExpr & other );
-	virtual ~TupleAssignExpr();
-
-	TupleAssignExpr * set_stmtExpr( StmtExpr * newValue ) { stmtExpr = newValue; return this; }
-	StmtExpr * get_stmtExpr() const { return stmtExpr; }
-
-	virtual TupleAssignExpr * clone() const override { return new TupleAssignExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-
-	friend class ConverterNewToOld;
-  private:
-    TupleAssignExpr( StmtExpr * stmts );
-};
-
-/// StmtExpr represents a GCC 'statement expression', e.g. ({ int x = 5; x; })
-class StmtExpr : public Expression {
-public:
-	CompoundStmt * statements;
-	std::list< ObjectDecl * > returnDecls; // return variable(s) for stmt expression
-	std::list< Expression * > dtors; // destructor(s) for return variable(s)
-
-	// readonly
-	ExprStmt * resultExpr = nullptr;
-
-	StmtExpr( CompoundStmt * statements );
-	StmtExpr( const StmtExpr & other );
-	virtual ~StmtExpr();
-
-	bool get_lvalue() const final;
-
-	CompoundStmt * get_statements() const { return statements; }
-	StmtExpr * set_statements( CompoundStmt * newValue ) { statements = newValue; return this; }
-
-	// call to set the result type of this StmtExpr based on its body
-	void computeResult();
-
-	std::list< ObjectDecl * > & get_returnDecls() { return returnDecls; }
-	std::list< Expression * > & get_dtors() { return dtors; }
-
-	virtual StmtExpr * clone() const override { return new StmtExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class UniqueExpr : public Expression {
-public:
-	Expression * expr;
-	ObjectDecl * object;
-	VariableExpr * var;
-
-	UniqueExpr( Expression * expr, long long idVal = -1 );
-	UniqueExpr( const UniqueExpr & other );
-	~UniqueExpr();
-
-	Expression * get_expr() const { return expr; }
-	UniqueExpr * set_expr( Expression * newValue ) { expr = newValue; return this; }
-
-	ObjectDecl * get_object() const { return object; }
-	UniqueExpr * set_object( ObjectDecl * newValue ) { object = newValue; return this; }
-
-	VariableExpr * get_var() const { return var; }
-	UniqueExpr * set_var( VariableExpr * newValue ) { var = newValue; return this; }
-
-	int get_id() const { return id; }
-
-	virtual UniqueExpr * clone() const override { return new UniqueExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-
-private:
-	int id;
-	static long long count;
-};
-
-struct InitAlternative {
-public:
-	Type * type = nullptr;
-	Designation * designation = nullptr;
-	InitAlternative( Type * type, Designation * designation );
-	InitAlternative( const InitAlternative & other );
-	InitAlternative & operator=( const Initializer & other ) = delete; // at the moment this isn't used, and I don't want to implement it
-	~InitAlternative();
-};
-
-class UntypedInitExpr : public Expression {
-public:
-	Expression * expr;
-	std::list<InitAlternative> initAlts;
-
-	UntypedInitExpr( Expression * expr, const std::list<InitAlternative> & initAlts );
-	UntypedInitExpr( const UntypedInitExpr & other );
-	~UntypedInitExpr();
-
-	Expression * get_expr() const { return expr; }
-	UntypedInitExpr * set_expr( Expression * newValue ) { expr = newValue; return this; }
-
-	std::list<InitAlternative> & get_initAlts() { return initAlts; }
-
-	virtual UntypedInitExpr * clone() const override { return new UntypedInitExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class InitExpr : public Expression {
-public:
-	Expression * expr;
-	Designation * designation;
-
-	InitExpr( Expression * expr, Designation * designation );
-	InitExpr( const InitExpr & other );
-	~InitExpr();
-
-	Expression * get_expr() const { return expr; }
-	InitExpr * set_expr( Expression * newValue ) { expr = newValue; return this; }
-
-	Designation * get_designation() const { return designation; }
-	InitExpr * set_designation( Designation * newValue ) { designation = newValue; return this; }
-
-	virtual InitExpr * clone() const override { return new InitExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// expression that contains a deleted identifier - should never make it past the resolver.
-class DeletedExpr : public Expression {
-public:
-	Expression * expr;
-	Declaration * deleteStmt;
-
-	DeletedExpr( Expression * expr, Declaration * deleteStmt );
-	DeletedExpr( const DeletedExpr & other );
-	~DeletedExpr();
-
-	virtual DeletedExpr * clone() const override { return new DeletedExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// expression wrapping the use of a default argument - should never make it past the resolver.
-class DefaultArgExpr : public Expression {
-public:
-	Expression * expr;
-
-	DefaultArgExpr( Expression * expr );
-	DefaultArgExpr( const DefaultArgExpr & other );
-	~DefaultArgExpr();
-
-	virtual DefaultArgExpr * clone() const override { return new DefaultArgExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// C11 _Generic expression
-class GenericExpr : public Expression {
-public:
-	struct Association {
-		Type * type = nullptr;
-		Expression * expr = nullptr;
-		bool isDefault = false;
-
-		Association( Type * type, Expression * expr );
-		Association( Expression * expr );
-		Association( const Association & other );
-		Association & operator=( const Association & other ) = delete; // at the moment this isn't used, and I don't want to implement it
-		~Association();
-	};
-
-	Expression * control;
-	std::list<Association> associations;
-
-	GenericExpr( Expression * control, const std::list<Association> & assoc );
-	GenericExpr( const GenericExpr & other );
-	virtual ~GenericExpr();
-
-	virtual GenericExpr * clone() const override { return new GenericExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/FunctionDecl.cc
===================================================================
--- src/SynTree/FunctionDecl.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,123 +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.
-//
-// FunctionDecl.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Dec 16 15:11:20 2019
-// Update Count     : 77
-//
-
-#include <cassert>               // for assert
-#include <list>                  // for list
-#include <ostream>               // for operator<<, ostream, basic_ostream
-#include <string>                // for operator<<, string, char_traits, ope...
-
-#include "Attribute.h"           // for Attribute
-#include "CodeGen/FixMain.h"     // for FixMain
-#include "Common/utility.h"      // for maybeClone, printAll
-#include "Declaration.h"         // for FunctionDecl, FunctionDecl::Parent
-#include "Expression.h"
-#include "LinkageSpec.h"         // for Spec, linkageName, Cforall
-#include "Statement.h"           // for CompoundStmt
-#include "Type.h"                // for Type, FunctionType, Type::FuncSpecif...
-#include "DeclReplacer.h"
-
-extern bool translation_unit_nomain;
-
-FunctionDecl::FunctionDecl( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage, FunctionType *type, CompoundStmt *statements, std::list< Attribute * > attributes, Type::FuncSpecifiers fs )
-	: Parent( name, scs, linkage, attributes, fs ), type( type ), statements( statements ) {
-	// hack forcing the function "main" to have Cforall linkage to replace main even if it is inside an extern
-	if ( name == "main" ) {
-		set_linkage( CodeGen::FixMain::mainLinkage() );
-	} // if
-}
-
-FunctionDecl::FunctionDecl( const FunctionDecl &other )
-		: Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ) {
-
-	DeclReplacer::DeclMap declMap;
-	for ( auto p : group_iterate( other.type->parameters, type->parameters ) ) {
-		declMap[ std::get<0>(p) ] = std::get<1>(p);
-	}
-	for ( auto p : group_iterate( other.type->returnVals, type->returnVals ) ) {
-		declMap[ std::get<0>(p) ] = std::get<1>(p);
-	}
-	if ( ! declMap.empty() ) {
-		DeclReplacer::replace( this, declMap );
-	}
-	cloneAll( other.withExprs, withExprs );
-}
-
-FunctionDecl::~FunctionDecl() {
-	delete type;
-	delete statements;
-	deleteAll( withExprs );
-}
-
-FunctionDecl * FunctionDecl::newFunction( const std::string & name, FunctionType * type, CompoundStmt * statements ) {
-	return new FunctionDecl( name, Type::StorageClasses(), LinkageSpec::C, type, statements );
-}
-
-void FunctionDecl::print( std::ostream &os, Indenter indent ) const {
-	using std::endl;
-	using std::string;
-
-	if ( name != "" ) {
-		os << name << ": ";
-	} // if
-	if ( linkage != LinkageSpec::Cforall ) {
-		os << LinkageSpec::name( linkage ) << " ";
-	} // if
-
-	printAll( attributes, os, indent );
-
-	get_storageClasses().print( os );
-	get_funcSpec().print( os );
-
-	if ( type ) {
-		type->print( os, indent );
-	} else {
-		os << "untyped entity ";
-	} // if
-
-	if ( !withExprs.empty() ) {
-		os << indent << "... with clause" << std::endl;
-		os << indent + 1;
-		printAll( withExprs, os, indent + 1 );
-	}
-
-	if ( statements ) {
-		os << indent << "... with body" << endl << indent+1;
-		statements->print( os, indent+1 );
-	} // if
-}
-
-void FunctionDecl::printShort( std::ostream &os, Indenter indent ) const {
-	using std::endl;
-	using std::string;
-
-	if ( name != "" ) {
-		os << name << ": ";
-	} // if
-
-	get_storageClasses().print( os );
-	get_funcSpec().print( os );
-
-	if ( type ) {
-		type->print( os, indent );
-	} else {
-		os << "untyped entity ";
-	} // if
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/FunctionType.cc
===================================================================
--- src/SynTree/FunctionType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,81 +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.
-//
-// FunctionType.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  1 17:21:00 2017
-// Update Count     : 2
-//
-
-#include <list>              // for list
-#include <ostream>           // for operator<<, basic_ostream, ostream, endl
-#include <string>            // for operator<<, char_traits, string
-
-#include "Common/utility.h"  // for cloneAll, deleteAll, printAll
-#include "Declaration.h"     // for DeclarationWithType
-#include "Tuples/Tuples.h"   // for isTtype
-#include "Type.h"            // for FunctionType, Type, Type::Qualifiers
-
-class Attribute;
-
-FunctionType::FunctionType( const Type::Qualifiers &tq, bool isVarArgs, const std::list< Attribute * > & attributes ) : Type( tq, attributes ), isVarArgs( isVarArgs ) {
-}
-
-FunctionType::FunctionType( const FunctionType &other ) : Type( other ), isVarArgs( other.isVarArgs ) {
-	cloneAll( other.returnVals, returnVals );
-	cloneAll( other.parameters, parameters );
-}
-
-FunctionType::~FunctionType() {
-	deleteAll( returnVals );
-	deleteAll( parameters );
-}
-
-namespace {
-	bool containsTtype( const std::list<DeclarationWithType * > & l ) {
-		if ( ! l.empty() ) {
-			return Tuples::isTtype( l.back()->get_type() );
-		}
-		return false;
-	}
-}
-
-bool FunctionType::isTtype() const {
-	return containsTtype( returnVals ) || containsTtype( parameters );
-}
-
-void FunctionType::print( std::ostream &os, Indenter indent ) const {
-	using std::string;
-	using std::endl;
-
-	Type::print( os, indent );
-	os << "function" << endl;
-	if ( ! parameters.empty() ) {
-		os << indent << "... with parameters" << endl;
-		printAll( parameters, os, indent+1 );
-		if ( isVarArgs ) {
-			os << indent+1 << "and a variable number of other arguments" << endl;
-		} // if
-	} else if ( isVarArgs ) {
-		os << indent+1 << "accepting unspecified arguments" << endl;
-	} // if
-	os << indent << "... returning";
-	if ( returnVals.empty() ) {
-		os << " nothing" << endl;
-	} else {
-		os << endl;
-		printAll( returnVals, os, indent+1 );
-	} // if
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Initializer.cc
===================================================================
--- src/SynTree/Initializer.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,142 +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.
-//
-// Initializer.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Aug 21 09:53:15 2017
-// Update Count     : 30
-//
-
-#include "Initializer.h"
-
-#include <cassert>                   // for assertf
-#include <ostream>                   // for ostream, operator<<, basic_ostream
-#include <string>                    // for operator<<, string, char_traits
-
-#include "Common/utility.h"          // for maybeClone, cloneAll, deleteAll
-#include "Expression.h"              // for Expression
-#include "Statement.h"               // for Statement
-#include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
-
-Designation::Designation( const std::list< Expression * > & designators ) : designators( designators ) {}
-Designation::Designation( const Designation & other ) : BaseSyntaxNode( other ) {
-	// std::cerr << "cloning designation" << std::endl;
-	cloneAll( other.designators, designators );
-	// std::cerr << "finished cloning designation" << std::endl;
-}
-
-Designation::~Designation() {
-	// std::cerr << "destroying designation" << std::endl;
-	deleteAll( designators );
-	// std::cerr << "finished destroying designation" << std::endl;
-}
-
-void Designation::print( std::ostream &os, Indenter indent ) const {
-	if ( ! designators.empty() ) {
-		os << "... designated by: " << std::endl;
-		for ( const Expression * d : designators ) {
-			os << indent+1;
-			d->print(os, indent+1 );
-			os << std::endl;
-		}
-	} // if
-}
-
-Initializer::Initializer( bool maybeConstructed ) : maybeConstructed( maybeConstructed ) {}
-Initializer::Initializer( const Initializer & other ) : BaseSyntaxNode( other ), maybeConstructed( other.maybeConstructed ) {
-}
-Initializer::~Initializer() {}
-
-SingleInit::SingleInit( Expression *v, bool maybeConstructed ) : Initializer( maybeConstructed ), value ( v ) {
-}
-
-SingleInit::SingleInit( const SingleInit &other ) : Initializer(other), value ( maybeClone( other.value ) ) {
-}
-
-SingleInit::~SingleInit() {
-	delete value;
-}
-
-void SingleInit::print( std::ostream &os, Indenter indent ) const {
-	os << "Simple Initializer: ";
-	value->print( os, indent );
-}
-
-
-ListInit::ListInit( const std::list<Initializer*> &inits, const std::list<Designation *> &des, bool maybeConstructed )
-	: Initializer( maybeConstructed ), initializers( inits ), designations( des ) {
-		// handle the common case where a ListInit is created without designations by making a list of empty designations with the same length as the initializer
-		if ( designations.empty() ) {
-			for ( auto & i : initializers ) {
-				(void)i;
-				designations.push_back( new Designation( {} ) );
-			}
-		}
-		assertf( initializers.size() == designations.size(), "Created ListInit with mismatching initializers (%zd) and designations (%zd)", initializers.size(), designations.size() );
-}
-
-ListInit::ListInit( const ListInit & other ) : Initializer( other ) {
-	cloneAll( other.initializers, initializers );
-	cloneAll( other.designations, designations );
-}
-
-ListInit::~ListInit() {
-	deleteAll( initializers );
-	deleteAll( designations );
-}
-
-void ListInit::print( std::ostream &os, Indenter indent ) const {
-	os << "Compound initializer: " << std::endl;
-	for ( auto p : group_iterate( designations, initializers ) ) {
-		const Designation * d = std::get<0>(p);
-		const Initializer * init = std::get<1>(p);
-		os << indent+1;
-		init->print( os, indent+1 );
-		os << std::endl;
-		if ( ! d->designators.empty() ) {
-			os << indent+1;
-			d->print( os, indent+1 );
-		}
-	}
-}
-
-
-ConstructorInit::ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init ) : Initializer( true ), ctor( ctor ), dtor( dtor ), init( init ) {}
-ConstructorInit::ConstructorInit( const ConstructorInit &other ) : Initializer( other ), ctor( maybeClone( other.ctor ) ), dtor( maybeClone( other.dtor ) ), init( maybeClone( other.init ) ) {
-}
-
-ConstructorInit::~ConstructorInit() {
-	delete ctor;
-	delete dtor;
-	delete init;
-}
-
-void ConstructorInit::print( std::ostream &os, Indenter indent ) const {
-	os << "Constructor initializer: " << std::endl;
-	if ( ctor ) {
-		os << indent << "... initially constructed with ";
-		ctor->print( os, indent+1 );
-	} // if
-
-	if ( dtor ) {
-		os << indent << "... destructed with ";
-		dtor->print( os, indent+1 );
-	}
-
-	if ( init ) {
-		os << indent << "... with fallback C-style initializer: ";
-		init->print( os, indent+1 );
-	}
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Initializer.h
===================================================================
--- src/SynTree/Initializer.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,151 +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.
-//
-// Initializer.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed Aug  9 10:19:00 2017
-// Update Count     : 22
-//
-
-#pragma once
-
-#include <iosfwd>            // for ostream
-#include <list>              // for list, list<>::const_iterator, list<>::it...
-
-#include "BaseSyntaxNode.h"  // for BaseSyntaxNode
-#include "Mutator.h"         // for Mutator
-#include "Visitor.h"         // for Visitor
-
-class Expression;
-class Statement;
-
-// Designation: list of designator (NameExpr, VariableExpr, and ConstantExpr) expressions that specify an object being initialized.
-class Designation : public BaseSyntaxNode {
-public:
-	std::list< Expression * > designators;
-
-	Designation( const std::list< Expression * > & designators );
-	Designation( const Designation & other );
-	virtual ~Designation();
-
-	std::list< Expression * > & get_designators() { return designators; }
-
-	virtual Designation * clone() const override { return new Designation( *this ); };
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Designation * acceptMutator( Mutator &m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
-};
-
-const std::list<Designation *> noDesignators;
-
-// Initializer: base class for object initializers (provide default values)
-class Initializer : public BaseSyntaxNode {
-  public:
-	Initializer( bool maybeConstructed );
-	Initializer( const Initializer & other );
-	virtual ~Initializer();
-
-	bool get_maybeConstructed() const { return maybeConstructed; }
-
-	virtual Initializer *clone() const override = 0;
-	virtual void accept( Visitor & v ) override = 0;
-	virtual void accept( Visitor & v ) const override = 0;
-	virtual Initializer *acceptMutator( Mutator &m ) override = 0;
-	virtual void print( std::ostream &os, Indenter indent = {} ) const override = 0;
-  private:
-	bool maybeConstructed;
-};
-
-// SingleInit represents an initializer for a common object (e.g., int x = 4)
-class SingleInit : public Initializer {
-  public:
-	//Constant *value;
-	Expression *value;	// has to be a compile-time constant
-
-	SingleInit( Expression *value, bool maybeConstructed = false );
-	SingleInit( const SingleInit &other );
-	virtual ~SingleInit();
-
-	Expression *get_value() { return value; }
-	void set_value( Expression *newValue ) { value = newValue; }
-
-	virtual SingleInit *clone() const override { return new SingleInit( *this); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
-};
-
-// ListInit represents an initializer that is composed recursively of a list of initializers; this is used to initialize
-// an array or aggregate
-class ListInit : public Initializer {
-  public:
-	std::list<Initializer *> initializers;  // order *is* important
-	std::list<Designation *> designations;  // order/length is consistent with initializers
-
-	ListInit( const std::list<Initializer*> &initializers,
-			  const std::list<Designation *> &designators = {}, bool maybeConstructed = false );
-	ListInit( const ListInit & other );
-	virtual ~ListInit();
-
-	std::list<Designation *> & get_designations() { return designations; }
-	std::list<Initializer *> & get_initializers() { return initializers; }
-
-	typedef std::list<Initializer*>::iterator iterator;
-	typedef std::list<Initializer*>::const_iterator const_iterator;
-	iterator begin() { return initializers.begin(); }
-	iterator end() { return initializers.end(); }
-	const_iterator begin() const { return initializers.begin(); }
-	const_iterator end() const { return initializers.end(); }
-
-	virtual ListInit *clone() const override { return new ListInit( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
-};
-
-// ConstructorInit represents an initializer that is either a constructor expression or
-// a C-style initializer.
-// It should not be necessary to create ConstructorInit nodes manually. Instead, set maybeConstructed
-// to true on SingleInit or ListInit constructors if object should be constructed.
-class ConstructorInit : public Initializer {
-  public:
-	Statement * ctor;
-	Statement * dtor;
-	// C-style initializer made up of SingleInit and ListInit nodes to use as a fallback
-	// if an appropriate constructor definition is not found by the resolver
-	Initializer * init;
-
-	ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init );
-	ConstructorInit( const ConstructorInit &other );
-	virtual ~ConstructorInit();
-
-	void set_ctor( Statement * newValue ) { ctor = newValue; }
-	Statement * get_ctor() const { return ctor; }
-	void set_dtor( Statement * newValue ) { dtor = newValue; }
-	Statement * get_dtor() const { return dtor; }
-	void set_init( Initializer * newValue ) { init = newValue; }
-	Initializer * get_init() const { return init; }
-
-	ConstructorInit *clone() const override { return new ConstructorInit( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
-
-  private:
-};
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/InlineMemberDecl.cc
===================================================================
--- src/SynTree/InlineMemberDecl.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,57 +1,0 @@
-#include <list>                  // for list
-#include <ostream>               // for operator<<, ostream, basic_ostream
-#include <string>                // for operator<<, string, char_traits, ope...
-
-#include "Attribute.h"           // for Attribute
-#include "Declaration.h"
-#include "Common/utility.h"      // for maybeClone, printAll
-#include "LinkageSpec.h"         // for Spec, linkageName, Cforall
-#include "Type.h"                // for Type, Type::StorageClasses, Type::Fu...
-
-InlineMemberDecl::InlineMemberDecl( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage,
-Type * type, const std::list< Attribute * >attributes, Type::FuncSpecifiers fs) 
-    : Parent( name, scs, linkage, attributes, fs ), type( type ) {}
-
-InlineMemberDecl::InlineMemberDecl( const InlineMemberDecl &other) 
-    : Parent( other), type( maybeClone( other.type ) ) {}
-
-InlineMemberDecl::~InlineMemberDecl() { delete type; }
-
-InlineMemberDecl * InlineMemberDecl::newInlineMemberDecl( const std::string &name, Type * type ) {
-    return new InlineMemberDecl( name, Type::StorageClasses(), LinkageSpec::C, type );
-}
-
-void InlineMemberDecl::print( std::ostream &os, Indenter indent ) const {
-    if ( name != "" ) os << name << ": ";
-
-	if ( linkage != LinkageSpec::Cforall ) {
-		os << LinkageSpec::name( linkage ) << " ";
-	} // if
-
-	get_storageClasses().print( os );
-
-	if ( type ) {
-		type->print( os, indent );
-	} else {
-		os << " untyped entity ";
-	} // if
-
-	if ( ! attributes.empty() ) {
-		os << std::endl << indent << "... with attributes:" << std::endl;
-		printAll( attributes, os, indent+1 );
-	} // if
-
-}
-
-void InlineMemberDecl::printShort( std::ostream &os, Indenter indent ) const {
-    if ( name != "" ) os << name << ": ";
-
-	get_storageClasses().print( os );
-
-	if ( type ) {
-		type->print( os, indent );
-	} else {
-		os << "untyped entity ";
-	} // if
-    
-}
Index: c/SynTree/Label.h
===================================================================
--- src/SynTree/Label.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,56 +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.
-//
-// Label.h --
-//
-// Author           : Rob Schluntz
-// Created On       : Wed Jun 8 12:53:12 2016
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:52:44 2017
-// Update Count     : 3
-//
-
-#pragma once
-
-#include <string>
-#include <list>
-#include <iostream>
-#include "SynTree.h"
-
-class Label {
-  public:
-	Label( const std::string & name = "", Statement * labelled = 0, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : name( name ), labelled( labelled ), attributes( attributes ) {}
-	Label( const char * name, Statement * labelled = 0 ) : name( name ), labelled( labelled ) {}
-
-	const std::string & get_name() const { return name; }
-	void set_name( const std::string & newValue ) { name = newValue; }
-
-	Statement * get_statement() const { return labelled; }
-	void set_statement( Statement * newValue ) { labelled = newValue; }
-	std::list< Attribute * >& get_attributes() { return attributes; }
-
-	operator std::string() const { return name; }
-	bool empty() { return name.empty(); }
-
-	std::string name;
-	Statement * labelled;
-	std::list< Attribute * > attributes;
-};
-
-inline bool operator==( Label l1, Label l2 ) { return l1.get_name() == l2.get_name(); }
-inline bool operator!=( Label l1, Label l2 ) { return ! (l1 == l2); }
-inline bool operator<( Label l1, Label l2 ) { return l1.get_name() < l2.get_name(); }
-// inline Label operator+( Label l1, Label l2 ) { return l1.get_name() + l2.get_name(); }
-// inline Label operator+( Label l1, const char * str ) { return l1.get_name() + Label( str ); }
-inline std::ostream & operator<<( std::ostream & out, const Label & l ) { return out << l.get_name(); }
-
-static const std::list< Label > noLabels;
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/LinkageSpec.cc
===================================================================
--- src/SynTree/LinkageSpec.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,58 +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.
-//
-// LinkageSpec.cc --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Sat May 16 13:22:09 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Mar  2 16:13:00 2020
-// Update Count     : 29
-//
-
-#include <cassert>
-#include <memory>   // for unique_ptr
-#include <string>
-using namespace std;
-
-#include "LinkageSpec.h"
-#include "Common/CodeLocation.h"
-#include "Common/SemanticError.h"
-
-namespace LinkageSpec {
-	Spec update( CodeLocation location, Spec spec, const string * cmd ) {
-		assert( cmd );
-		unique_ptr<const string> guard( cmd ); // allocated by lexer
-		if ( *cmd == "\"Cforall\"" ) {
-			spec.is_mangled = true;
-			return spec;
-		} else if ( *cmd == "\"C\"" ) {
-			spec.is_mangled = false;
-			return spec;
-		} else {
-			SemanticError( location, "Invalid linkage specifier " + *cmd );
-		} // if
-	} // update
-
-	string name( Spec spec ) {
-		switch ( spec ) {
-		  case Intrinsic: return "intrinsic";
-		  case C: return "C";
-		  case Cforall: return "Cforall";
-		  case AutoGen: return "autogenerated cfa";
-		  case Compiler: return "compiler built-in";
-		  case BuiltinCFA: return "cfa built-in";
-		  case BuiltinC: return "c built-in";
-		  default: return "<unnamed linkage spec>";
-		} // siwtch
-	} // name
-} // LinkageSpec
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/LinkageSpec.h
===================================================================
--- src/SynTree/LinkageSpec.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,85 +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.
-//
-// LinkageSpec.h --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Sat May 16 13:24:28 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Mar  2 16:13:00 2020
-// Update Count     : 21
-//
-
-#pragma once
-
-#include <string>
-
-struct CodeLocation;
-
-namespace LinkageSpec {
-	// Bitflags for linkage specifiers
-	enum {
-		Mangle = 1 << 0,
-		Generate = 1 << 1,
-		Overrideable = 1 << 2,
-		Builtin = 1 << 3,
-		GccBuiltin = 1 << 4,
-	};
-
-	// Bitflag type for storage classes
-	union Spec {
-		unsigned int val;
-		struct {
-			bool is_mangled : 1;
-			bool is_generatable : 1;
-			bool is_overridable : 1;
-			bool is_builtin : 1;
-			bool is_gcc_builtin : 1;
-		};
-		constexpr Spec( unsigned int val ) : val( val ) {}
-		constexpr Spec( Spec const & other ) : val( other.val ) {}
-		constexpr Spec & operator=( const Spec & ) = default;
-		// Operators may go here.
-		// Supports == and !=
-		constexpr operator unsigned int() const { return val; }
-	};
-
-
-	Spec update( CodeLocation location, Spec spec, const std::string * cmd );
-	// If cmd = "C" returns a Spec that is old_spec with is_mangled = false
-	// If cmd = "Cforall" returns old_spec Spec with is_mangled = true
-
-	std::string name( Spec );
-
-	// To Update: LinkageSpec::isXyz( cur_spec ) -> cur_spec.is_xyz
-	inline bool isMangled( Spec spec ) { return spec.is_mangled; }
-	inline bool isGeneratable( Spec spec ) { return spec.is_generatable; }
-	inline bool isOverridable( Spec spec ) { return spec.is_overridable; }
-	inline bool isBuiltin( Spec spec ) { return spec.is_builtin; }
-	inline bool isGccBuiltin( Spec spec ) { return spec.is_gcc_builtin; }
-
-	// Pre-defined flag combinations:
-	// C built-in defined in prelude
-	constexpr Spec const Intrinsic = { Mangle | Generate | Overrideable | Builtin };
-	// ordinary
-	constexpr Spec const Cforall = { Mangle | Generate };
-	// not overloadable, not mangled
-	constexpr Spec const C = { Generate };
-	// built by translator (struct assignment)
-	constexpr Spec const AutoGen = { Mangle | Generate | Overrideable };
-	// gcc internal
-	constexpr Spec const Compiler = { Mangle | Builtin | GccBuiltin };
-	// mangled builtins
-	constexpr Spec const BuiltinCFA = { Mangle | Generate | Builtin };
-	// non-mangled builtins
-	constexpr Spec const BuiltinC = { Generate | Builtin };
-};
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Makefile
===================================================================
--- src/SynTree/Makefile	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,22 +1,0 @@
-CXX=g++
-CXXFLAGS=-g -Wall #-Wno-unused
-
-SRCS:=Type.cc Constant.cc Expression.cc Statement.cc CodeGenVisitor.cc
-OBJECTS:=$(SRCS:.cc=.o)
-DEPS:=$(SRCS:.cc=.d)
-
-# libSynTree.a:  $(OBJECTS)
-# 	ar -rs $@ $(OBJECTS)
-#	$(CXX) $(CXXFLAGS) $(OBJS) -o $@ $(EXTRALIBS)
-
-%.d: %.cc
-	g++ -M $(CXXFLAGS) $< | sed -e '1s/^\(.*\)\.o/\1.d \1.o/' > $@
-
-all: $(OBJECTS)
-
-ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
-endif
-
-clean:
-	rm -f cfa $(OBJECTS) $(DEPS) core
Index: c/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,170 +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.
-//
-// Mutator.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Feb  1 09:26:49 2022
-// Update Count     : 20
-//
-#pragma once
-
-#include <cassert>                 // for assert
-
-#include "Common/SemanticError.h"  // for SemanticError
-#include "SynTree/SynTree.h"       // for AST nodes
-
-class Mutator {
-  protected:
-	Mutator() = default;
-	virtual ~Mutator() = default;
-  public:
-	virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) = 0;
-	virtual DeclarationWithType * mutate( FunctionDecl * functionDecl ) = 0;
-	virtual Declaration * mutate( StructDecl * aggregateDecl ) = 0;
-	virtual Declaration * mutate( UnionDecl * aggregateDecl ) = 0;
-	virtual Declaration * mutate( EnumDecl * aggregateDecl ) = 0;
-	virtual Declaration * mutate( TraitDecl * aggregateDecl ) = 0;
-	virtual Declaration * mutate( TypeDecl * typeDecl ) = 0;
-	virtual Declaration * mutate( TypedefDecl * typeDecl ) = 0;
-	virtual AsmDecl * mutate( AsmDecl * asmDecl ) = 0;
-	virtual DirectiveDecl * mutate( DirectiveDecl * directiveDecl ) = 0;
-	virtual StaticAssertDecl * mutate( StaticAssertDecl * assertDecl ) = 0;
-	virtual DeclarationWithType * mutate( InlineMemberDecl * InlineMemberDecl ) = 0;
-
-	virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) = 0;
-	virtual Statement * mutate( ExprStmt * exprStmt ) = 0;
-	virtual Statement * mutate( AsmStmt * asmStmt ) = 0;
-	virtual Statement * mutate( DirectiveStmt * dirStmt ) = 0;
-	virtual Statement * mutate( IfStmt * ifStmt ) = 0;
-	virtual Statement * mutate( WhileDoStmt * whileDoStmt ) = 0;
-	virtual Statement * mutate( ForStmt * forStmt ) = 0;
-	virtual Statement * mutate( SwitchStmt * switchStmt ) = 0;
-	virtual Statement * mutate( CaseStmt * caseStmt ) = 0;
-	virtual Statement * mutate( BranchStmt * branchStmt ) = 0;
-	virtual Statement * mutate( ReturnStmt * returnStmt ) = 0;
-	virtual Statement * mutate( ThrowStmt * throwStmt ) = 0;
-	virtual Statement * mutate( TryStmt * tryStmt ) = 0;
-	virtual Statement * mutate( CatchStmt * catchStmt ) = 0;
-	virtual Statement * mutate( FinallyStmt * catchStmt ) = 0;
-	virtual Statement * mutate( SuspendStmt * suspendStmt ) = 0;
-	virtual Statement * mutate( WaitForStmt * waitforStmt ) = 0;
-	virtual Declaration * mutate( WithStmt * withStmt ) = 0;
-	virtual NullStmt * mutate( NullStmt * nullStmt ) = 0;
-	virtual Statement * mutate( DeclStmt * declStmt ) = 0;
-	virtual Statement * mutate( ImplicitCtorDtorStmt * impCtorDtorStmt ) = 0;
-	virtual Statement * mutate( MutexStmt * mutexStmt ) = 0;
-
-	virtual Expression * mutate( ApplicationExpr * applicationExpr ) = 0;
-	virtual Expression * mutate( UntypedExpr * untypedExpr ) = 0;
-	virtual Expression * mutate( NameExpr * nameExpr ) = 0;
-	virtual Expression * mutate( AddressExpr * addrExpr ) = 0;
-	virtual Expression * mutate( LabelAddressExpr * labAddressExpr ) = 0;
-	virtual Expression * mutate( CastExpr * castExpr ) = 0;
-	virtual Expression * mutate( KeywordCastExpr * castExpr ) = 0;
-	virtual Expression * mutate( VirtualCastExpr * castExpr ) = 0;
-	virtual Expression * mutate( UntypedMemberExpr * memberExpr ) = 0;
-	virtual Expression * mutate( MemberExpr * memberExpr ) = 0;
-	virtual Expression * mutate( VariableExpr * variableExpr ) = 0;
-	virtual Expression * mutate( ConstantExpr * constantExpr ) = 0;
-	virtual Expression * mutate( SizeofExpr * sizeofExpr ) = 0;
-	virtual Expression * mutate( AlignofExpr * alignofExpr ) = 0;
-	virtual Expression * mutate( UntypedOffsetofExpr * offsetofExpr ) = 0;
-	virtual Expression * mutate( OffsetofExpr * offsetofExpr ) = 0;
-	virtual Expression * mutate( OffsetPackExpr * offsetPackExpr ) = 0;
-	virtual Expression * mutate( LogicalExpr * logicalExpr ) = 0;
-	virtual Expression * mutate( ConditionalExpr * conditionalExpr ) = 0;
-	virtual Expression * mutate( CommaExpr * commaExpr ) = 0;
-	virtual Expression * mutate( TypeExpr * typeExpr ) = 0;
-	virtual Expression * mutate( DimensionExpr * dimensionExpr ) = 0;
-	virtual Expression * mutate( AsmExpr * asmExpr ) = 0;
-	virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) = 0;
-	virtual Expression * mutate( ConstructorExpr * ctorExpr ) = 0;
-	virtual Expression * mutate( CompoundLiteralExpr * compLitExpr ) = 0;
-	virtual Expression * mutate( RangeExpr * rangeExpr ) = 0;
-	virtual Expression * mutate( UntypedTupleExpr * tupleExpr ) = 0;
-	virtual Expression * mutate( TupleExpr * tupleExpr ) = 0;
-	virtual Expression * mutate( TupleIndexExpr * tupleExpr ) = 0;
-	virtual Expression * mutate( TupleAssignExpr * assignExpr ) = 0;
-	virtual Expression * mutate( StmtExpr  * stmtExpr ) = 0;
-	virtual Expression * mutate( UniqueExpr  * uniqueExpr ) = 0;
-	virtual Expression * mutate( UntypedInitExpr  * initExpr ) = 0;
-	virtual Expression * mutate( InitExpr  * initExpr ) = 0;
-	virtual Expression * mutate( DeletedExpr * delExpr ) = 0;
-	virtual Expression * mutate( DefaultArgExpr * argExpr ) = 0;
-	virtual Expression * mutate( GenericExpr * genExpr ) = 0;
-	virtual Expression * mutate( QualifiedNameExpr * qualifiedNameExpr ) = 0;
-
-	virtual Type * mutate( VoidType * basicType ) = 0;
-	virtual Type * mutate( BasicType * basicType ) = 0;
-	virtual Type * mutate( PointerType * pointerType ) = 0;
-	virtual Type * mutate( ArrayType * arrayType ) = 0;
-	virtual Type * mutate( ReferenceType * refType ) = 0;
-	virtual Type * mutate( QualifiedType * qualType ) = 0;
-	virtual Type * mutate( FunctionType * functionType ) = 0;
-	virtual Type * mutate( StructInstType * aggregateUseType ) = 0;
-	virtual Type * mutate( UnionInstType * aggregateUseType ) = 0;
-	virtual Type * mutate( EnumInstType * aggregateUseType ) = 0;
-	virtual Type * mutate( TraitInstType * aggregateUseType ) = 0;
-	virtual Type * mutate( TypeInstType * aggregateUseType ) = 0;
-	virtual Type * mutate( TupleType * tupleType ) = 0;
-	virtual Type * mutate( TypeofType * typeofType ) = 0;
-	virtual Type * mutate( VTableType * vtableType ) = 0;
-	virtual Type * mutate( AttrType * attrType ) = 0;
-	virtual Type * mutate( VarArgsType * varArgsType ) = 0;
-	virtual Type * mutate( ZeroType * zeroType ) = 0;
-	virtual Type * mutate( OneType * oneType ) = 0;
-	virtual Type * mutate( GlobalScopeType * globalType ) = 0;
-
-	virtual Designation * mutate( Designation * designation ) = 0 ;
-	virtual Initializer * mutate( SingleInit * singleInit ) = 0 ;
-	virtual Initializer * mutate( ListInit * listInit ) = 0 ;
-	virtual Initializer * mutate( ConstructorInit * ctorInit ) = 0 ;
-
-	virtual Constant * mutate( Constant * constant ) = 0;
-
-	virtual Attribute * mutate( Attribute * attribute ) = 0;
-
-	virtual TypeSubstitution * mutate( TypeSubstitution * sub ) = 0;
-};
-
-template< typename TreeType, typename MutatorType >
-inline TreeType *maybeMutate( TreeType *tree, MutatorType &mutator ) {
-	if ( tree ) {
-		TreeType *newnode = dynamic_cast< TreeType * >( tree->acceptMutator( mutator ) );
-		assert( newnode );
-		return newnode;
-	} else {
-		return 0;
-	} // if
-}
-
-template< typename Container, typename MutatorType >
-inline void mutateAll( Container &container, MutatorType &mutator ) {
-	SemanticErrorException errors;
-	for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
-		try {
-			if ( *i ) {
-///		    *i = (*i)->acceptMutator( mutator );
-				*i = dynamic_cast< typename Container::value_type >( (*i)->acceptMutator( mutator ) );
-				assert( *i );
-			} // if
-		} catch( SemanticErrorException &e ) {
-			errors.append( e );
-		} // try
-	} // for
-	if ( ! errors.isEmpty() ) {
-		throw errors;
-	} // if
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/NamedTypeDecl.cc
===================================================================
--- src/SynTree/NamedTypeDecl.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,80 +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.
-//
-// NamedTypeDecl.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Dec 16 15:11:40 2019
-// Update Count     : 17
-//
-
-#include <list>                  // for list
-#include <ostream>               // for operator<<, ostream, basic_ostream
-#include <string>                // for operator<<, string, char_traits, ope...
-
-#include "Common/utility.h"      // for printAll, cloneAll, deleteAll, maybe...
-#include "Declaration.h"         // for NamedTypeDecl, DeclarationWithType
-#include "LinkageSpec.h"         // for Spec, Cforall, linkageName
-#include "Type.h"                // for Type, Type::StorageClasses
-#include "CompilationState.h"
-
-NamedTypeDecl::NamedTypeDecl( const std::string &name, Type::StorageClasses scs, Type *base )
-	: Parent( name, scs, LinkageSpec::Cforall ), base( base ) {}
-
-NamedTypeDecl::NamedTypeDecl( const NamedTypeDecl &other )
-	: Parent( other ), base( maybeClone( other.base ) ) {
-	cloneAll( other.assertions, assertions );
-}
-
-NamedTypeDecl::~NamedTypeDecl() {
-	delete base;
-	deleteAll( assertions );
-}
-
-void NamedTypeDecl::print( std::ostream &os, Indenter indent ) const {
-	using namespace std;
-
-	if ( ! name.empty() ) {
-		if( deterministic_output && isUnboundType(name) ) os << "[unbound]:";
-		else os << name << ": ";
-	}
-
-	if ( linkage != LinkageSpec::Cforall ) {
-		os << LinkageSpec::name( linkage ) << " ";
-	} // if
-	get_storageClasses().print( os );
-	os << typeString();
-	if ( base ) {
-		os << " for ";
-		base->print( os, indent+1 );
-	} // if
-	if ( ! assertions.empty() ) {
-		os << endl << indent << "... with assertions" << endl;
-		printAll( assertions, os, indent+1 );
-	} // if
-}
-
-void NamedTypeDecl::printShort( std::ostream &os, Indenter indent ) const {
-	using namespace std;
-
-	if ( name != "" ) os << name << ": ";
-	get_storageClasses().print( os );
-	os << typeString();
-	if ( base ) {
-		os << " for ";
-		base->print( os, indent+1 );
-	} // if
-}
-
-const char * TypedefDecl::typeString() const { return "typedef"; }
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/ObjectDecl.cc
===================================================================
--- src/SynTree/ObjectDecl.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,104 +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.
-//
-// ObjectDecl.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Dec 16 15:12:03 2019
-// Update Count     : 61
-//
-
-#include <list>                  // for list
-#include <ostream>               // for operator<<, ostream, basic_ostream
-#include <string>                // for operator<<, string, char_traits, ope...
-
-#include "Attribute.h"           // for Attribute
-#include "Common/utility.h"      // for maybeClone, printAll
-#include "Declaration.h"         // for ObjectDecl, ObjectDecl::Parent
-#include "Expression.h"          // for Expression
-#include "Initializer.h"         // for Initializer
-#include "LinkageSpec.h"         // for Spec, linkageName, Cforall
-#include "Type.h"                // for Type, Type::StorageClasses, Type::Fu...
-
-ObjectDecl::ObjectDecl( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage, Expression *bitfieldWidth, Type *type, Initializer *init, const std::list< Attribute * > attributes, Type::FuncSpecifiers fs )
-	: Parent( name, scs, linkage, attributes, fs ), type( type ), init( init ), bitfieldWidth( bitfieldWidth ) {
-}
-
-ObjectDecl::ObjectDecl( const ObjectDecl &other )
-	: Parent( other ), type( maybeClone( other.type ) ), init( maybeClone( other.init ) ), bitfieldWidth( maybeClone( other.bitfieldWidth ) ) {
-}
-
-ObjectDecl::~ObjectDecl() {
-	delete type;
-	delete init;
-	delete bitfieldWidth;
-}
-
-ObjectDecl * ObjectDecl::newObject( const std::string & name, Type * type, Initializer * init ) {
-	return new ObjectDecl( name, Type::StorageClasses(), LinkageSpec::C, 0, type, init );
-}
-
-void ObjectDecl::print( std::ostream &os, Indenter indent ) const {
-	if ( name != "" ) os << name << ": ";
-
-	if ( linkage != LinkageSpec::Cforall ) {
-		os << LinkageSpec::name( linkage ) << " ";
-	} // if
-
-	get_storageClasses().print( os );
-
-	if ( type ) {
-		type->print( os, indent );
-	} else {
-		os << " untyped entity ";
-	} // if
-
-	if ( init ) {
-		os << " with initializer (" << (init->get_maybeConstructed() ? "maybe constructed" : "not constructed") << ")" << std::endl << indent+1;
-		init->print( os, indent+1 );
-		os << std::endl;
-	} // if
-
-	if ( ! attributes.empty() ) {
-		os << std::endl << indent << "... with attributes:" << std::endl;
-		printAll( attributes, os, indent+1 );
-	}
-
-	if ( bitfieldWidth ) {
-		os << indent << " with bitfield width ";
-		bitfieldWidth->print( os );
-	} // if
-}
-
-void ObjectDecl::printShort( std::ostream &os, Indenter indent ) const {
-#if 0
-	if ( get_mangleName() != "") {
-		os << get_mangleName() << ": ";
-	} else
-#endif
-	if ( name != "" ) os << name << ": ";
-
-	get_storageClasses().print( os );
-
-	if ( type ) {
-		type->print( os, indent );
-	} else {
-		os << "untyped entity ";
-	} // if
-
-	if ( bitfieldWidth ) {
-		os << "with bitfield width ";
-		bitfieldWidth->print( os );
-	} // if
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/PointerType.cc
===================================================================
--- src/SynTree/PointerType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,69 +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.
-//
-// PointerType.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  1 17:17:13 2017
-// Update Count     : 6
-//
-
-#include <list>              // for list
-#include <ostream>           // for operator<<, ostream
-
-#include "Common/utility.h"  // for maybeClone
-#include "Expression.h"      // for Expression
-#include "Type.h"            // for PointerType, Type, Type::Qualifiers
-
-class Attribute;
-
-PointerType::PointerType( const Type::Qualifiers &tq, Type *base, const std::list< Attribute * > & attributes )
-	: Type( tq, attributes ), base( base ), dimension( 0 ), isVarLen( false ), isStatic( false ) {
-}
-
-PointerType::PointerType( const Type::Qualifiers &tq, Type *base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes )
-	: Type( tq, attributes ), base( base ), dimension( dimension ), isVarLen( isVarLen ), isStatic( isStatic ) {
-}
-
-PointerType::PointerType( const PointerType &other )
-	: Type( other ), base( maybeClone( other.base ) ), dimension( maybeClone( other.dimension ) ),
-	  isVarLen( other.isVarLen ), isStatic( other.isStatic ) {
-}
-
-PointerType::~PointerType() {
-	delete base;
-	delete dimension;
-}
-
-void PointerType::print( std::ostream &os, Indenter indent ) const {
-	Type::print( os, indent );
-	if ( ! is_array() ) {
-		os << "pointer to ";
-	} else {
-		os << "decayed ";
-		if ( isStatic ) {
-			os << "static ";
-		} // if
-		if ( isVarLen ) {
-			os << "variable length array of ";
-		} else if ( dimension ) {
-			os << "array of ";
-			dimension->print( os, indent );
-			os << " ";
-		} // if
-	}
-	if ( base ) {
-		base->print( os, indent );
-	} // if
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/ReferenceToType.cc
===================================================================
--- src/SynTree/ReferenceToType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,222 +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.
-//
-// ReferenceToType.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Feb 23 16:38:54 2017
-// Update Count     : 24
-//
-
-#include <cassert>            // for assert
-#include <list>               // for list, _List_const_iterator, list<>::cons...
-#include <ostream>            // for operator<<, basic_ostream, ostream, endl
-#include <string>             // for string, operator<<, char_traits, operator==
-
-#include "Common/utility.h"   // for printAll, cloneAll, deleteAll
-#include "Declaration.h"      // for StructDecl, UnionDecl, EnumDecl, Declara...
-#include "Expression.h"       // for Expression
-#include "Type.h"             // for TypeInstType, StructInstType, UnionInstType
-#include "TypeSubstitution.h" // for TypeSubstitution
-#include "CompilationState.h"
-
-class Attribute;
-
-ReferenceToType::ReferenceToType( const Type::Qualifiers &tq, const std::string &name, const std::list< Attribute * > & attributes ) : Type( tq, attributes ), name( name ), hoistType( false ) {
-}
-
-ReferenceToType::ReferenceToType( const ReferenceToType &other ) : Type( other ), name( other.name ), hoistType( other.hoistType ) {
-	cloneAll( other.parameters, parameters );
-}
-
-ReferenceToType::~ReferenceToType() {
-	deleteAll( parameters );
-}
-
-void ReferenceToType::print( std::ostream &os, Indenter indent ) const {
-	using std::endl;
-
-	Type::print( os, indent );
-	os << "instance of " << typeString() << " " << name << " ";
-	if ( ! parameters.empty() ) {
-		os << endl << indent << "... with parameters" << endl;
-		printAll( parameters, os, indent+1 );
-	} // if
-}
-
-namespace {
-	void doLookup( const std::list< Declaration * > & members, const std::string & name, std::list< Declaration* > & foundDecls ) {
-		for ( Declaration * decl : members ) {
-			if ( decl->name == name ) {
-				foundDecls.push_back( decl );
-			} // if
-		} // for
-	}
-} // namespace
-
-StructInstType::StructInstType( const Type::Qualifiers & tq, StructDecl * baseStruct, const std::list< Attribute * > & attributes ) :
-		Parent( tq, baseStruct->name, attributes ), baseStruct( baseStruct ) {}
-
-std::string StructInstType::typeString() const { return "struct"; }
-
-const std::list<TypeDecl*>* StructInstType::get_baseParameters() const {
-	if ( ! baseStruct ) return nullptr;
-	return &baseStruct->get_parameters();
-}
-
-std::list<TypeDecl*>* StructInstType::get_baseParameters() {
-	if ( ! baseStruct ) return nullptr;
-	return &baseStruct->get_parameters();
-}
-
-bool StructInstType::isComplete() const { return baseStruct ? baseStruct->has_body() : false; }
-
-AggregateDecl * StructInstType::getAggr() const { return baseStruct; }
-
-TypeSubstitution StructInstType::genericSubstitution() const {
-	return TypeSubstitution( get_baseParameters()->begin(), get_baseParameters()->end(), parameters.begin() );
-}
-
-void StructInstType::lookup( const std::string &name, std::list< Declaration* > &foundDecls ) const {
-	assert( baseStruct );
-	doLookup( baseStruct->members, name, foundDecls );
-}
-
-void StructInstType::print( std::ostream &os, Indenter indent ) const {
-	using std::endl;
-
-	if ( baseStruct == nullptr ) ReferenceToType::print( os, indent );
-	else {
-		Type::print( os, indent );
-		os << "instance of " << typeString() << " " << name << " with body " << baseStruct->has_body();
-		if ( ! parameters.empty() ) {
-			os << endl << indent << "... with parameters" << endl;
-			printAll( parameters, os, indent+1 );
-		} // if
-	} // if
-}
-
-
-UnionInstType::UnionInstType( const Type::Qualifiers & tq, UnionDecl * baseUnion, const std::list< Attribute * > & attributes ) :
-		Parent( tq, baseUnion->name, attributes ), baseUnion( baseUnion ) {}
-
-std::string UnionInstType::typeString() const { return "union"; }
-
-std::list< TypeDecl * > * UnionInstType::get_baseParameters() {
-	if ( ! baseUnion ) return nullptr;
-	return &baseUnion->get_parameters();
-}
-
-const std::list< TypeDecl * > * UnionInstType::get_baseParameters() const {
-	if ( ! baseUnion ) return nullptr;
-	return &baseUnion->get_parameters();
-}
-
-bool UnionInstType::isComplete() const { return baseUnion ? baseUnion->has_body() : false; }
-
-AggregateDecl * UnionInstType::getAggr() const { return baseUnion; }
-
-TypeSubstitution UnionInstType::genericSubstitution() const {
-	return TypeSubstitution( get_baseParameters()->begin(), get_baseParameters()->end(), parameters.begin() );
-}
-
-void UnionInstType::lookup( const std::string &name, std::list< Declaration* > &foundDecls ) const {
-	assert( baseUnion );
-	doLookup( baseUnion->members, name, foundDecls );
-}
-
-void UnionInstType::print( std::ostream &os, Indenter indent ) const {
-	using std::endl;
-
-	if ( baseUnion == nullptr ) ReferenceToType::print( os, indent );
-	else {
-		Type::print( os, indent );
-		os << "instance of " << typeString() << " " << name << " with body " << baseUnion->has_body();
-		if ( ! parameters.empty() ) {
-			os << endl << indent << "... with parameters" << endl;
-			printAll( parameters, os, indent+1 );
-		} // if
-	} // if
-}
-
-
-EnumInstType::EnumInstType( const Type::Qualifiers & tq, EnumDecl * baseEnum, const std::list< Attribute * > & attributes ) :
-		Parent( tq, baseEnum->get_name(), attributes ), baseEnum( baseEnum ) {}
-
-std::string EnumInstType::typeString() const { return "enum"; }
-
-bool EnumInstType::isComplete() const { return baseEnum ? baseEnum->has_body() : false; }
-
-AggregateDecl * EnumInstType::getAggr() const { return baseEnum; }
-
-void EnumInstType::print( std::ostream &os, Indenter indent ) const {
-	using std::endl;
-
-	if ( baseEnum == nullptr ) ReferenceToType::print( os, indent );
-	else {
-		Type::print( os, indent );
-		os << "instance of " << typeString() << " " << name << " with body " << baseEnum->has_body();
-	} // if
-}
-
-
-std::string TraitInstType::typeString() const { return "trait"; }
-
-TraitInstType::TraitInstType( const Type::Qualifiers & tq, TraitDecl * baseTrait, const std::list< Attribute * > & attributes ) : Parent( tq, baseTrait->name, attributes ), baseTrait( baseTrait ) {}
-
-TraitInstType::TraitInstType( const TraitInstType &other ) : Parent( other ), baseTrait( other.baseTrait ) {
-}
-
-TraitInstType::~TraitInstType() {
-}
-
-bool TraitInstType::isComplete() const { assert( false ); }
-
-TypeInstType::TypeInstType( const Type::Qualifiers &tq, const std::string &name, TypeDecl *baseType, const std::list< Attribute * > & attributes ) : Parent( tq, name, attributes ) {
-	set_baseType( baseType );
-}
-
-TypeInstType::TypeInstType( const Type::Qualifiers &tq, const std::string &name, bool isFtype, const std::list< Attribute * > & attributes ) : Parent( tq, name, attributes ), baseType( 0 ), isFtype( isFtype ) {
-}
-
-TypeInstType::TypeInstType( const TypeInstType &other ) : Parent( other ), baseType( other.baseType ), isFtype( other.isFtype ) {
-}
-
-
-TypeInstType::~TypeInstType() {
-	// delete baseType; //This is shared and should not be deleted
-}
-
-void TypeInstType::set_baseType( TypeDecl *newValue ) {
-	baseType = newValue;
-	isFtype = newValue->get_kind() == TypeDecl::Ftype;
-}
-
-std::string TypeInstType::typeString() const { return "type"; }
-
-bool TypeInstType::isComplete() const { return baseType->isComplete(); }
-
-void TypeInstType::print( std::ostream &os, Indenter indent ) const {
-	using std::endl;
-
-	Type::print( os, indent );
-	os << "instance of " << typeString() << " ";
-	if( deterministic_output && isUnboundType(name) ) os << "[unbound]";
-	else os << name;
-	os << " (" << ( isFtype ? "" : "not" ) << " function type)";
-	if ( ! parameters.empty() ) {
-		os << endl << indent << "... with parameters" << endl;
-		printAll( parameters, os, indent+1 );
-	} // if
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/ReferenceType.cc
===================================================================
--- src/SynTree/ReferenceType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,52 +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.
-//
-// PointerType.cc --
-//
-// Author           : Rob Schluntz
-// Created On       : Fri May 12 18:12:15 2017
-// Last Modified By : Rob Schluntz
-// Last Modified On : Fri May 12 18:12:15 2017
-// Update Count     : 1
-//
-
-#include "Type.h"
-#include "Expression.h"
-#include "TypeSubstitution.h"
-#include "Common/utility.h"
-
-ReferenceType::ReferenceType( const Type::Qualifiers &tq, Type *base, const std::list< Attribute * > & attributes )
-	: Type( tq, attributes ), base( base ) {
-	assertf( base, "Reference Type with a null base created." );
-}
-
-ReferenceType::ReferenceType( const ReferenceType &other )
-	: Type( other ), base( maybeClone( other.base ) ) {
-}
-
-ReferenceType::~ReferenceType() {
-	delete base;
-}
-
-int ReferenceType::referenceDepth() const {
-	return base->referenceDepth()+1;
-}
-
-TypeSubstitution ReferenceType::genericSubstitution() const { return base->genericSubstitution(); }
-
-void ReferenceType::print( std::ostream &os, Indenter indent ) const {
-	Type::print( os, indent );
-	os << "reference to ";
-	if ( base ) {
-		base->print( os, indent );
-	} // if
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Statement.cc
===================================================================
--- src/SynTree/Statement.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,605 +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.
-//
-// Statement.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  2 20:19:33 2022
-// Update Count     : 90
-//
-
-#include "SynTree/Statement.h"
-
-#include <stddef.h>                // for NULL
-#include <cassert>                 // for assert, assertf
-#include <iostream>                // for operator<<, basic_ostream, endl
-#include <list>                    // for list, list<>::const_iterator, _Lis...
-#include <string>                  // for operator<<, string, char_traits
-
-#include "Common/SemanticError.h"  // for SemanticError
-#include "Common/utility.h"        // for maybeClone, cloneAll, deleteAll
-#include "Declaration.h"           // for Declaration
-#include "Expression.h"            // for Expression, ConstantExpr
-#include "Statement.h"             // for Statement, ForStmt, AsmStmt, Catch...
-#include "SynTree/Label.h"         // for Label, operator<<
-
-using namespace std;
-
-
-Statement::Statement( const list<Label> & labels ) : labels( labels ) {}
-
-void Statement::print( ostream & os, Indenter indent ) const {
-	if ( ! labels.empty() ) {
-		os << indent << "... Labels: {";
-		for ( const Label & l : labels ) {
-			os << l << ",";
-		}
-		os << "}" << endl;
-	}
-}
-
-Statement::~Statement() {}
-
-ExprStmt::ExprStmt( Expression * expr ) : Statement(), expr( expr ) {}
-
-ExprStmt::ExprStmt( const ExprStmt & other ) : Statement( other ), expr( maybeClone( other.expr ) ) {}
-
-ExprStmt::~ExprStmt() {
-	delete expr;
-}
-
-void ExprStmt::print( ostream & os, Indenter indent ) const {
-	os << "Expression Statement:" << endl << indent + 1;
-	expr->print( os, indent + 1 );
-}
-
-
-AsmStmt::AsmStmt( bool voltile, Expression * instruction, const list<Expression *> output, const list<Expression *> input, const list<ConstantExpr *> clobber, const list<Label> gotolabels ) : Statement(), voltile( voltile ), instruction( instruction ), output( output ), input( input ), clobber( clobber ), gotolabels( gotolabels ) {}
-
-AsmStmt::AsmStmt( const AsmStmt & other ) : Statement( other ), voltile( other.voltile ), instruction( maybeClone( other.instruction ) ), gotolabels( other.gotolabels ) {
-  cloneAll( other.output, output );
-  cloneAll( other.input, input );
-  cloneAll( other.clobber, clobber );
-}
-
-AsmStmt::~AsmStmt() {
-	delete instruction;
-	deleteAll( output );
-	deleteAll( input );
-	deleteAll( clobber );
-}
-
-void AsmStmt::print( ostream & os, Indenter indent ) const {
-	os << "Assembler Statement:" << endl;
-	os << indent + 1 << "instruction: " << endl << indent;
-	instruction->print( os, indent + 1 );
-	if ( ! output.empty() ) {
-		os << endl << indent + 1 << "output: " << endl;
-		printAll( output, os, indent + 1 );
-	} // if
-	if ( ! input.empty() ) {
-		os << indent + 1 << "input: " << endl;
-		printAll( input, os, indent + 1 );
-	} // if
-	if ( ! clobber.empty() ) {
-		os << indent + 1 << "clobber: " << endl;
-		printAll( clobber, os, indent + 1 );
-	} // if
-}
-
-
-DirectiveStmt::DirectiveStmt( const string & directive ) : Statement(), directive( directive ) {}
-
-void DirectiveStmt::print( ostream & os, Indenter ) const {
-	os << "GCC Directive:" << directive << endl;
-}
-
-
-const char * BranchStmt::brType[] = {
-	"Goto", "Break", "Continue", "Fall Through", "Fall Through Default",
-};
-
-BranchStmt::BranchStmt( Label target, Type type ) :
-	Statement(), originalTarget( target ), target( target ), computedTarget( nullptr ), type( type ) {
-	//actually this is a syntactic error signaled by the parser
-	if ( type == BranchStmt::Goto && target.empty() ) {
-		SemanticError( target.get_statement()->location, "goto without target");
-	}
-}
-
-BranchStmt::BranchStmt( Expression * computedTarget, Type type ) :
-	Statement(), computedTarget( computedTarget ), type( type ) {
-	if ( type != BranchStmt::Goto || computedTarget == nullptr ) {
-		SemanticError( computedTarget->location, "Computed target not valid in branch statement");
-	}
-}
-
-void BranchStmt::print( ostream & os, Indenter indent ) const {
-	assertf(type < BranchStmts, "CFA internal error: invalid branch statement" );
-	os << "Branch (" << brType[type] << ")" << endl ;
-	if ( target != "" ) os << indent + 1 << "with target: " << target << endl;
-	if ( originalTarget != "" ) os << indent + 1 << "with original target: " << originalTarget << endl;
-	if ( computedTarget != nullptr ) os << indent + 1 << "with computed target: " << computedTarget << endl;
-}
-
-ReturnStmt::ReturnStmt( Expression * expr ) : Statement(), expr( expr ) {}
-
-ReturnStmt::ReturnStmt( const ReturnStmt & other ) : Statement( other ), expr( maybeClone( other.expr ) ) {}
-
-ReturnStmt::~ReturnStmt() {
-	delete expr;
-}
-
-void ReturnStmt::print( ostream & os, Indenter indent ) const {
-	os << "Return Statement, returning: ";
-	if ( expr != nullptr ) {
-		os << endl << indent + 1;
-		expr->print( os, indent + 1 );
-	}
-	os << endl;
-}
-
-IfStmt::IfStmt( Expression * condition, Statement * then, Statement * else_, const list<Statement *> initialization ):
-	Statement(), condition( condition ), then( then ), else_( else_ ), initialization( initialization ) {}
-
-IfStmt::IfStmt( const IfStmt & other ) :
-	Statement( other ), condition( maybeClone( other.condition ) ), then( maybeClone( other.then ) ), else_( maybeClone( other.else_ ) ) {
-	cloneAll( other.initialization, initialization );
-}
-
-IfStmt::~IfStmt() {
-	deleteAll( initialization );
-	delete condition;
-	delete then;
-	delete else_;
-}
-
-void IfStmt::print( ostream & os, Indenter indent ) const {
-	os << "If on condition: " << endl;
-	os << indent + 1;
-	condition->print( os, indent + 1 );
-
-	if ( !initialization.empty() ) {
-		os << indent << "... with initialization: \n";
-		for ( const Statement * stmt : initialization ) {
-			os << indent + 1;
-			stmt->print( os, indent + 1 );
-		}
-		os << endl;
-	}
-
-	os << indent << "... then: " << endl;
-
-	os << indent + 1;
-	then->print( os, indent + 1 );
-
-	if ( else_ != nullptr ) {
-		os << indent << "... else: " << endl;
-		os << indent + 1;
-		else_->print( os, indent + 1 );
-	} // if
-}
-
-SwitchStmt::SwitchStmt( Expression * condition, const list<Statement *> & statements ):
-	Statement(), condition( condition ), statements( statements ) {
-}
-
-SwitchStmt::SwitchStmt( const SwitchStmt & other ):
-	Statement( other ), condition( maybeClone( other.condition ) ) {
-	cloneAll( other.statements, statements );
-}
-
-SwitchStmt::~SwitchStmt() {
-	delete condition;
-	// destroy statements
-	deleteAll( statements );
-}
-
-void SwitchStmt::print( ostream & os, Indenter indent ) const {
-	os << "Switch on condition: ";
-	condition->print( os );
-	os << endl;
-
-	for ( const Statement * stmt : statements ) {
-		stmt->print( os, indent + 1 );
-	}
-}
-
-CaseStmt::CaseStmt( Expression * condition, const list<Statement *> & statements, bool deflt ) :
-		Statement(), condition( condition ), stmts( statements ), _isDefault( deflt ) {
-	if ( isDefault() && condition != nullptr ) SemanticError( condition, "default case with condition: " );
-}
-
-CaseStmt::CaseStmt( const CaseStmt & other ) :
-		Statement( other ), condition( maybeClone(other.condition ) ), _isDefault( other._isDefault ) {
-	cloneAll( other.stmts, stmts );
-}
-
-CaseStmt::~CaseStmt() {
-	delete condition;
-	deleteAll( stmts );
-}
-
-CaseStmt * CaseStmt::makeDefault( const list<Label> & labels, list<Statement *> stmts ) {
-	CaseStmt * stmt = new CaseStmt( nullptr, stmts, true );
-	stmt->labels = labels;
-	return stmt;
-}
-
-void CaseStmt::print( ostream & os, Indenter indent ) const {
-	if ( isDefault() ) os << indent << "Default ";
-	else {
-		os << indent << "Case ";
-		condition->print( os, indent );
-	} // if
-	os << endl;
-
-	for ( Statement * stmt : stmts ) {
-		os << indent + 1;
-		stmt->print( os, indent + 1 );
-	}
-}
-
-WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, const list< Statement * > & initialization, bool isDoWhile ):
-	Statement(), condition( condition ), body( body ), else_( nullptr ), initialization( initialization ), isDoWhile( isDoWhile) {
-}
-
-WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, Statement * else_, const list< Statement * > & initialization, bool isDoWhile ):
-	Statement(), condition( condition), body( body ), else_( else_ ), initialization( initialization ), isDoWhile( isDoWhile) {
-}
-
-WhileDoStmt::WhileDoStmt( const WhileDoStmt & other ):
-	Statement( other ), condition( maybeClone( other.condition ) ), body( maybeClone( other.body ) ), isDoWhile( other.isDoWhile ) {
-}
-
-WhileDoStmt::~WhileDoStmt() {
-	delete body;
-	delete condition;
-}
-
-void WhileDoStmt::print( ostream & os, Indenter indent ) const {
-	os << "While on condition: " << endl ;
-	condition->print( os, indent + 1 );
-
-	os << indent << "... with body: " << endl;
-
-	if ( body != nullptr ) body->print( os, indent + 1 );
-}
-
-ForStmt::ForStmt( const list<Statement *> initialization, Expression * condition, Expression * increment, Statement * body, Statement * else_ ):
-	Statement(), initialization( initialization ), condition( condition ), increment( increment ), body( body ), else_( else_ ) {
-}
-
-ForStmt::ForStmt( const ForStmt & other ):
-	Statement( other ), condition( maybeClone( other.condition ) ), increment( maybeClone( other.increment ) ), body( maybeClone( other.body ) ), else_( maybeClone( other.else_ ) ) {
-		cloneAll( other.initialization, initialization );
-
-}
-
-ForStmt::~ForStmt() {
-	deleteAll( initialization );
-	delete condition;
-	delete increment;
-	delete body;
-	delete else_;
-}
-
-void ForStmt::print( ostream & os, Indenter indent ) const {
-	Statement::print( os, indent ); // print labels
-
-	os << "For Statement" << endl;
-
-	if ( ! initialization.empty() ) {
-		os << indent << "... initialization: \n";
-		for ( Statement * stmt : initialization ) {
-			os << indent + 1;
-			stmt->print( os, indent + 1 );
-		}
-	}
-
-	if ( condition != nullptr ) {
-		os << indent << "... condition: \n" << indent + 1;
-		condition->print( os, indent + 1 );
-	}
-
-	if ( increment != nullptr ) {
-		os << "\n" << indent << "... increment: \n" << indent + 1;
-		increment->print( os, indent + 1 );
-	}
-
-	if ( body != nullptr ) {
-		os << "\n" << indent << "... with body: \n" << indent + 1;
-		body->print( os, indent + 1 );
-	}
-
-	if ( else_ != nullptr ) {
-		os << "\n" << indent << "... with body: \n" << indent + 1;
-		else_->print( os, indent + 1 );
-	}
-	os << endl;
-}
-
-ThrowStmt::ThrowStmt( Kind kind, Expression * expr, Expression * target ) :
-		Statement(), kind(kind), expr(expr), target(target)	{
-	assertf(Resume == kind || nullptr == target, "Non-local termination throw is not accepted." );
-}
-
-ThrowStmt::ThrowStmt( const ThrowStmt & other ) :
-	Statement ( other ), kind( other.kind ), expr( maybeClone( other.expr ) ), target( maybeClone( other.target ) ) {
-}
-
-ThrowStmt::~ThrowStmt() {
-	delete expr;
-	delete target;
-}
-
-void ThrowStmt::print( ostream & os, Indenter indent) const {
-	if ( target ) os << "Non-Local ";
-	os << "Throw Statement, raising: ";
-	expr->print(os, indent + 1);
-	if ( target ) {
-		os << "... at: ";
-		target->print(os, indent + 1);
-	}
-}
-
-TryStmt::TryStmt( CompoundStmt * tryBlock, const list<CatchStmt *> & handlers, FinallyStmt * finallyBlock ) :
-	Statement(), block( tryBlock ),  handlers( handlers ), finallyBlock( finallyBlock ) {
-}
-
-TryStmt::TryStmt( const TryStmt & other ) : Statement( other ), block( maybeClone( other.block ) ), finallyBlock( maybeClone( other.finallyBlock ) ) {
-	cloneAll( other.handlers, handlers );
-}
-
-TryStmt::~TryStmt() {
-	delete block;
-	deleteAll( handlers );
-	delete finallyBlock;
-}
-
-void TryStmt::print( ostream & os, Indenter indent ) const {
-	os << "Try Statement" << endl;
-	os << indent << "... with block:" << endl << indent + 1;
-	block->print( os, indent + 1 );
-
-	// handlers
-	os << indent << "... and handlers:" << endl;
-	for ( const CatchStmt * stmt : handlers ) {
-		os << indent + 1;
-		stmt->print( os, indent + 1 );
-	}
-
-	// finally block
-	if ( finallyBlock != nullptr ) {
-		os << indent << "... and finally:" << endl << indent + 1;
-		finallyBlock->print( os, indent + 1 );
-	} // if
-}
-
-CatchStmt::CatchStmt( Kind kind, Declaration * decl, Expression * cond, Statement * body ) :
-	Statement(), kind ( kind ), decl ( decl ), cond ( cond ), body( body ) {
-		assertf( decl, "Catch clause must have a declaration." );
-}
-
-CatchStmt::CatchStmt( const CatchStmt & other ) :
-	Statement( other ), kind ( other.kind ), decl ( maybeClone( other.decl ) ), cond ( maybeClone( other.cond ) ), body( maybeClone( other.body ) ) {
-}
-
-CatchStmt::~CatchStmt() {
-	delete decl;
-	delete body;
-}
-
-void CatchStmt::print( ostream & os, Indenter indent ) const {
-	os << "Catch " << ((Terminate == kind) ? "Terminate" : "Resume") << " Statement" << endl;
-
-	os << indent << "... catching: ";
-	decl->printShort( os, indent + 1 );
-	os << endl;
-
-	if ( cond ) {
-		os << indent << "... with conditional:" << endl << indent + 1;
-		cond->print( os, indent + 1 );
-	}
-
-	os << indent << "... with block:" << endl;
-	os << indent + 1;
-	body->print( os, indent + 1 );
-}
-
-
-FinallyStmt::FinallyStmt( CompoundStmt * block ) : Statement(), block( block ) {
-}
-
-FinallyStmt::FinallyStmt( const FinallyStmt & other ) : Statement( other ), block( maybeClone( other.block ) ) {
-}
-
-FinallyStmt::~FinallyStmt() {
-	delete block;
-}
-
-void FinallyStmt::print( ostream & os, Indenter indent ) const {
-	os << "Finally Statement" << endl;
-	os << indent << "... with block:" << endl << indent + 1;
-	block->print( os, indent + 1 );
-}
-
-SuspendStmt::SuspendStmt( const SuspendStmt & other )
-	: Statement( other )
-	, then( maybeClone(other.then) )
-{}
-
-SuspendStmt::~SuspendStmt() {
-	delete then;
-}
-
-void SuspendStmt::print( ostream & os, Indenter indent ) const {
-	os << "Suspend Statement";
-	switch (type) {
-		case None     : os << " with implicit target"; break;
-		case Generator: os << " for generator"       ; break;
-		case Coroutine: os << " for coroutine"       ; break;
-	}
-	os << endl;
-	indent += 1;
-
-	if(then) {
-		os << indent << " with post statement :" << endl;
-		then->print( os, indent + 1);
-	}
-}
-
-WaitForStmt::WaitForStmt() : Statement() {
-	timeout.time      = nullptr;
-	timeout.statement = nullptr;
-	timeout.condition = nullptr;
- 	orelse .statement = nullptr;
-	orelse .condition = nullptr;
-}
-
-WaitForStmt::WaitForStmt( const WaitForStmt & other ) : Statement( other ) {
-	clauses.reserve( other.clauses.size() );
-	for( auto & ocl : other.clauses ) {
-		clauses.emplace_back();
-		clauses.back().target.function = ocl.target.function->clone();
-		cloneAll( ocl.target.arguments, clauses.back().target.arguments );
-		clauses.back().statement = ocl.statement->clone();
-		clauses.back().condition = ocl.condition->clone();
-	}
-
-	timeout.time      = other.timeout.time     ->clone();
-	timeout.statement = other.timeout.statement->clone();
-	timeout.condition = other.timeout.condition->clone();
-	orelse .statement = other.orelse .statement->clone();
-	orelse .condition = other.orelse .condition->clone();
-}
-
-WaitForStmt::~WaitForStmt() {
-	for( auto & clause : clauses ) {
-		delete clause.target.function;
-		deleteAll( clause.target.arguments );
-		delete clause.statement;
-		delete clause.condition;
-	}
-
-	delete timeout.time;
-	delete timeout.statement;
-	delete timeout.condition;
-
-	delete orelse.statement;
-	delete orelse.condition;
-}
-
-void WaitForStmt::print( ostream & os, Indenter indent ) const {
-	os << "Waitfor Statement" << endl;
-	indent += 1;
-	for( auto & clause : clauses ) {
-		os << indent << "target function :";
-		if(clause.target.function) { clause.target.function->print(os, indent + 1); }
-		os << endl << indent << "with arguments :" << endl;
-		for( auto & thing : clause.target.arguments) {
-			if(thing) { thing->print(os, indent + 1); }
-		}
-		os << indent << " with statment :" << endl;
-		if(clause.statement) { clause.statement->print(os, indent + 1); }
-
-		os << indent << " with condition :" << endl;
-		if(clause.condition) { clause.condition->print(os, indent + 1); }
-	}
-
-	os << indent << " timeout of :" << endl;
-	if(timeout.time) { timeout.time->print(os, indent + 1); }
-
-	os << indent << " with statment :" << endl;
-	if(timeout.statement) { timeout.statement->print(os, indent + 1); }
-
-	os << indent << " with condition :" << endl;
-	if(timeout.condition) { timeout.condition->print(os, indent + 1); }
-
-
-	os << indent << " else :" << endl;
-	if(orelse.statement) { orelse.statement->print(os, indent + 1); }
-
-	os << indent << " with condition :" << endl;
-	if(orelse.condition) { orelse.condition->print(os, indent + 1); }
-}
-
-
-WithStmt::WithStmt( const list< Expression * > & exprs, Statement * stmt ) : Declaration("", noStorageClasses, LinkageSpec::Cforall), exprs( exprs ), stmt( stmt ) {}
-WithStmt::WithStmt( const WithStmt & other ) : Declaration( other ), stmt( maybeClone( other.stmt ) ) {
-	cloneAll( other.exprs, exprs );
-}
-WithStmt::~WithStmt() {
-	deleteAll( exprs );
-	delete stmt;
-}
-
-void WithStmt::print( ostream & os, Indenter indent ) const {
-	os << "With statement" << endl;
-	os << indent << "... with expressions: " << endl;
-	printAll( exprs, os, indent + 1 );
-	os << indent << "... with statement:" << endl << indent + 1;
-	stmt->print( os, indent + 1 );
-}
-
-
-NullStmt::NullStmt( const list<Label> & labels ) : Statement( labels ) {
-}
-
-void NullStmt::print( ostream & os, Indenter indent ) const {
-	os << "Null Statement" << endl;
-	Statement::print( os, indent );
-}
-
-ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( Statement * callStmt ) : Statement(), callStmt( callStmt ) {
-	assert( callStmt );
-}
-
-ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( const ImplicitCtorDtorStmt & other ) : Statement( other ), callStmt( maybeClone( other.callStmt ) ) {
-}
-
-ImplicitCtorDtorStmt::~ImplicitCtorDtorStmt() {
-	delete callStmt;
-}
-
-void ImplicitCtorDtorStmt::print( ostream & os, Indenter indent ) const {
-	os << "Implicit Ctor Dtor Statement" << endl;
-	os << indent << "... with Ctor/Dtor: ";
-	callStmt->print( os, indent + 1);
-	os << endl;
-}
-
-MutexStmt::MutexStmt( Statement * stmt, const list<Expression *> mutexObjs )
-	: Statement(), stmt( stmt ), mutexObjs( mutexObjs ) { }
-
-MutexStmt::MutexStmt( const MutexStmt & other ) : Statement( other ), stmt( maybeClone( other.stmt ) ) {
-	cloneAll( other.mutexObjs, mutexObjs );
-}
-
-MutexStmt::~MutexStmt() {
-	deleteAll( mutexObjs );
-	delete stmt;
-}
-
-void MutexStmt::print( ostream & os, Indenter indent ) const {
-	os << "Mutex Statement" << endl;
-	os << indent << "... with Expressions: " << endl;
-	for (auto * obj : mutexObjs) {
-		os << indent + 1;
-		obj->print( os, indent + 1);
-		os << endl;
-	}
-	os << indent << "... with Statement: " << endl << indent + 1;
-	stmt->print( os, indent + 1 );
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Statement.h
===================================================================
--- src/SynTree/Statement.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,560 +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.
-//
-// Statement.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  2 20:15:30 2022
-// Update Count     : 98
-//
-
-#pragma once
-
-#include <iosfwd>                  // for ostream
-#include <list>                    // for list
-#include <memory>                  // for allocator
-#include <vector>				   // for vector
-
-#include "BaseSyntaxNode.h"        // for BaseSyntaxNode
-#include "Common/SemanticError.h"  // for SemanticError
-#include "Label.h"                 // for Label
-#include "Mutator.h"               // for Mutator
-#include "Visitor.h"               // for Visitor
-
-class CatchStmt;
-class ConstantExpr;
-class Declaration;
-class Expression;
-class FinallyStmt;
-
-class Statement : public BaseSyntaxNode {
-  public:
-	std::list<Label> labels;
-
-	Statement( const std::list<Label> & labels = {} );
-	virtual ~Statement();
-
-	std::list<Label> & get_labels() { return labels; }
-	const std::list<Label> & get_labels() const { return labels; }
-
-	virtual Statement * clone() const override = 0;
-	virtual void accept( Visitor & v ) override = 0;
-	virtual void accept( Visitor & v ) const override = 0;
-	virtual Statement * acceptMutator( Mutator & m ) override = 0;
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class CompoundStmt : public Statement {
-  public:
-	std::list<Statement*> kids;
-
-	CompoundStmt();
-	CompoundStmt( std::list<Statement *> stmts );
-	CompoundStmt( const CompoundStmt & other );
-	virtual ~CompoundStmt();
-
-	std::list<Statement*>& get_kids() { return kids; }
-	void push_back( Statement * stmt ) { kids.push_back( stmt ); }
-	void push_front( Statement * stmt ) { kids.push_front( stmt ); }
-
-	virtual CompoundStmt * clone() const override { return new CompoundStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual CompoundStmt * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class NullStmt : public Statement {
-  public:
-	NullStmt( const std::list<Label> & labels = {} );
-
-	virtual NullStmt * clone() const override { return new NullStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual NullStmt * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class ExprStmt : public Statement {
-  public:
-	Expression * expr;
-
-	ExprStmt( Expression * expr );
-	ExprStmt( const ExprStmt & other );
-	virtual ~ExprStmt();
-
-	Expression * get_expr() { return expr; }
-	void set_expr( Expression * newValue ) { expr = newValue; }
-
-	virtual ExprStmt * clone() const override { return new ExprStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class AsmStmt : public Statement {
-  public:
-	bool voltile;
-	Expression * instruction;
-	std::list<Expression *> output, input;
-	std::list<ConstantExpr *> clobber;
-	std::list<Label> gotolabels;
-
-	AsmStmt( bool voltile, Expression * instruction, const std::list<Expression *> output, const std::list<Expression *> input, const std::list<ConstantExpr *> clobber, const std::list<Label> gotolabels );
-	AsmStmt( const AsmStmt & other );
-	virtual ~AsmStmt();
-
-	bool get_voltile() { return voltile; }
-	void set_voltile( bool newValue ) { voltile = newValue; }
-	Expression * get_instruction() { return instruction; }
-	void set_instruction( Expression * newValue ) { instruction = newValue; }
-	std::list<Expression *> & get_output() { return output; }
-	void set_output( const std::list<Expression *> & newValue ) { output = newValue; }
-	std::list<Expression *> & get_input() { return input; }
-	void set_input( const std::list<Expression *> & newValue ) { input = newValue; }
-	std::list<ConstantExpr *> & get_clobber() { return clobber; }
-	void set_clobber( const std::list<ConstantExpr *> & newValue ) { clobber = newValue; }
-	std::list<Label> & get_gotolabels() { return gotolabels; }
-	void set_gotolabels( const std::list<Label> & newValue ) { gotolabels = newValue; }
-
-	virtual AsmStmt * clone() const override { return new AsmStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class DirectiveStmt : public Statement {
-	public:
-	std::string directive;
-
-	DirectiveStmt( const std::string & );
-	virtual ~DirectiveStmt(){}
-
-	virtual DirectiveStmt * clone() const override { return new DirectiveStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class IfStmt : public Statement {
-  public:
-	Expression * condition;
-	Statement * then;
-	Statement * else_;
-	std::list<Statement *> initialization;
-
-	IfStmt( Expression * condition, Statement * then, Statement * else_,
-			const std::list<Statement *> initialization = std::list<Statement *>() );
-	IfStmt( const IfStmt & other );
-	virtual ~IfStmt();
-
-	std::list<Statement *> & get_initialization() { return initialization; }
-	Expression * get_condition() { return condition; }
-	void set_condition( Expression * newValue ) { condition = newValue; }
-	Statement * get_then() { return then; }
-	void set_then( Statement * newValue ) { then = newValue; }
-	Statement * get_else() { return else_; }
-	void set_else( Statement * newValue ) { else_ = newValue; }
-
-	virtual IfStmt * clone() const override { return new IfStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class SwitchStmt : public Statement {
-  public:
-	Expression * condition;
-	std::list<Statement *> statements;
-
-	SwitchStmt( Expression * condition, const std::list<Statement *> & statements );
-	SwitchStmt( const SwitchStmt & other );
-	virtual ~SwitchStmt();
-
-	Expression * get_condition() { return condition; }
-	void set_condition( Expression * newValue ) { condition = newValue; }
-
-	std::list<Statement *> & get_statements() { return statements; }
-
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-
-	virtual SwitchStmt * clone() const override { return new SwitchStmt( *this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-
-};
-
-class CaseStmt : public Statement {
-  public:
-	Expression * condition;
-	std::list<Statement *> stmts;
-
-	CaseStmt( Expression * conditions, const std::list<Statement *> & stmts, bool isdef = false );
-	CaseStmt( const CaseStmt & other );
-	virtual ~CaseStmt();
-
-	static CaseStmt * makeDefault( const std::list<Label> & labels = {}, std::list<Statement *> stmts = std::list<Statement *>() );
-
-	bool isDefault() const { return _isDefault; }
-	void set_default(bool b) { _isDefault = b; }
-
-	Expression * & get_condition() { return condition; }
-	void set_condition( Expression * newValue ) { condition = newValue; }
-
-	std::list<Statement *> & get_statements() { return stmts; }
-	void set_statements( std::list<Statement *> & newValue ) { stmts = newValue; }
-
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-
-	virtual CaseStmt * clone() const override { return new CaseStmt( *this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-  private:
-	bool _isDefault;
-};
-
-class WhileDoStmt : public Statement {
-  public:
-	Expression * condition;
-	Statement * body;
-	Statement * else_;
-	std::list<Statement *> initialization;
-	bool isDoWhile;
-
-	WhileDoStmt( Expression * condition, Statement * body, const std::list<Statement *> & initialization, bool isDoWhile = false );
-	WhileDoStmt( Expression * condition, Statement * body, Statement * else_, const std::list<Statement *> & initialization, bool isDoWhile = false );
-	WhileDoStmt( const WhileDoStmt & other );
-	virtual ~WhileDoStmt();
-
-	Expression * get_condition() { return condition; }
-	void set_condition( Expression * newValue ) { condition = newValue; }
-	Statement * get_body() { return body; }
-	void set_body( Statement * newValue ) { body = newValue; }
-	bool get_isDoWhile() { return isDoWhile; }
-	void set_isDoWhile( bool newValue ) { isDoWhile = newValue; }
-
-	virtual WhileDoStmt * clone() const override { return new WhileDoStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class ForStmt : public Statement {
-  public:
-	std::list<Statement *> initialization;
-	Expression * condition;
-	Expression * increment;
-	Statement * body;
-	Statement * else_;
-
-	ForStmt( const std::list<Statement *> initialization, Expression * condition = nullptr, Expression * increment = nullptr, Statement * body = nullptr, Statement * else_ = nullptr );
-	ForStmt( const ForStmt & other );
-	virtual ~ForStmt();
-
-	std::list<Statement *> & get_initialization() { return initialization; }
-	Expression * get_condition() { return condition; }
-	void set_condition( Expression * newValue ) { condition = newValue; }
-	Expression * get_increment() { return increment; }
-	void set_increment( Expression * newValue ) { increment = newValue; }
-	Statement * get_body() { return body; }
-	void set_body( Statement * newValue ) { body = newValue; }
-
-	virtual ForStmt * clone() const override { return new ForStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class BranchStmt : public Statement {
-  public:
-	enum Type { Goto, Break, Continue, FallThrough, FallThroughDefault, BranchStmts };
-
-	// originalTarget kept for error messages.
-	const Label originalTarget;
-	Label target;
-	Expression * computedTarget;
-	Type type;
-
-	BranchStmt( Label target, Type );
-	BranchStmt( Expression * computedTarget, Type );
-
-	Label get_originalTarget() { return originalTarget; }
-	Label get_target() { return target; }
-	void set_target( Label newValue ) { target = newValue; }
-
-	Expression * get_computedTarget() { return computedTarget; }
-	void set_target( Expression * newValue ) { computedTarget = newValue; }
-
-	Type get_type() { return type; }
-	const char * get_typename() { return brType[ type ]; }
-
-	virtual BranchStmt * clone() const override { return new BranchStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-  private:
-	static const char * brType[];
-};
-
-class ReturnStmt : public Statement {
-  public:
-	Expression * expr;
-
-	ReturnStmt( Expression * expr );
-	ReturnStmt( const ReturnStmt & other );
-	virtual ~ReturnStmt();
-
-	Expression * get_expr() { return expr; }
-	void set_expr( Expression * newValue ) { expr = newValue; }
-
-	virtual ReturnStmt * clone() const override { return new ReturnStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class ThrowStmt : public Statement {
-  public:
-	enum Kind { Terminate, Resume };
-
-	const Kind kind;
-	Expression * expr;
-	Expression * target;
-
-	ThrowStmt( Kind kind, Expression * expr, Expression * target = nullptr );
-	ThrowStmt( const ThrowStmt & other );
-	virtual ~ThrowStmt();
-
-	Kind get_kind() { return kind; }
-	Expression * get_expr() { return expr; }
-	void set_expr( Expression * newExpr ) { expr = newExpr; }
-	Expression * get_target() { return target; }
-	void set_target( Expression * newTarget ) { target = newTarget; }
-
-	virtual ThrowStmt * clone() const override { return new ThrowStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class TryStmt : public Statement {
-  public:
-	CompoundStmt * block;
-	std::list<CatchStmt *> handlers;
-	FinallyStmt * finallyBlock;
-
-	TryStmt( CompoundStmt * tryBlock, const std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock = nullptr );
-	TryStmt( const TryStmt & other );
-	virtual ~TryStmt();
-
-	CompoundStmt * get_block() const { return block; }
-	void set_block( CompoundStmt * newValue ) { block = newValue; }
-	std::list<CatchStmt *>& get_catchers() { return handlers; }
-
-	FinallyStmt * get_finally() const { return finallyBlock; }
-	void set_finally( FinallyStmt * newValue ) { finallyBlock = newValue; }
-
-	virtual TryStmt * clone() const override { return new TryStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class CatchStmt : public Statement {
-  public:
-	enum Kind { Terminate, Resume };
-
-	const Kind kind;
-	Declaration * decl;
-	Expression * cond;
-	Statement * body;
-
-	CatchStmt( Kind kind, Declaration * decl,
-	           Expression * cond, Statement * body );
-	CatchStmt( const CatchStmt & other );
-	virtual ~CatchStmt();
-
-	Kind get_kind() { return kind; }
-	Declaration * get_decl() { return decl; }
-	void set_decl( Declaration * newValue ) { decl = newValue; }
-	Expression * get_cond() { return cond; }
-	void set_cond( Expression * newCond ) { cond = newCond; }
-	Statement * get_body() { return body; }
-	void set_body( Statement * newValue ) { body = newValue; }
-
-	virtual CatchStmt * clone() const override { return new CatchStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class FinallyStmt : public Statement {
-  public:
-	CompoundStmt * block;
-
-	FinallyStmt( CompoundStmt * block );
-	FinallyStmt( const FinallyStmt & other );
-	virtual ~FinallyStmt();
-
-	CompoundStmt * get_block() const { return block; }
-	void set_block( CompoundStmt * newValue ) { block = newValue; }
-
-	virtual FinallyStmt * clone() const override { return new FinallyStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class SuspendStmt : public Statement {
-  public:
-	CompoundStmt * then = nullptr;
-	enum Type { None, Coroutine, Generator } type = None;
-
-	SuspendStmt() = default;
-	SuspendStmt( const SuspendStmt & );
-	virtual ~SuspendStmt();
-
-	virtual SuspendStmt * clone() const override { return new SuspendStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class WaitForStmt : public Statement {
-  public:
-
-	struct Target {
-		Expression * function;
-		std::list<Expression * > arguments;
-	};
-
-	struct Clause {
-		Target       target;
-		Statement  * statement;
-		Expression * condition;
-	};
-
-	WaitForStmt();
-	WaitForStmt( const WaitForStmt & );
-	virtual ~WaitForStmt();
-
-	std::vector<Clause> clauses;
-
-	struct {
-		Expression * time;
-		Statement  * statement;
-		Expression * condition;
-	} timeout;
-
-	struct {
-		Statement  * statement;
-		Expression * condition;
-	} orelse;
-
-	virtual WaitForStmt * clone() const override { return new WaitForStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-
-};
-
-// class WithStmt : public Statement {
-// public:
-// 	std::list< Expression * > exprs;
-// 	Statement * stmt;
-
-// 	WithStmt( const std::list< Expression * > & exprs, Statement * stmt );
-// 	WithStmt( const WithStmt & other );
-// 	virtual ~WithStmt();
-
-// 	virtual WithStmt * clone() const override { return new WithStmt( *this ); }
-// 	virtual void accept( Visitor & v ) override { v.visit( this ); }
-// 	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-// 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-// 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-// };
-
-
-// represents a declaration that occurs as part of a compound statement
-class DeclStmt : public Statement {
-  public:
-	Declaration * decl;
-
-	DeclStmt( Declaration * decl );
-	DeclStmt( const DeclStmt & other );
-	virtual ~DeclStmt();
-
-	Declaration * get_decl() const { return decl; }
-	void set_decl( Declaration * newValue ) { decl = newValue; }
-
-	virtual DeclStmt * clone() const override { return new DeclStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-
-/// represents an implicit application of a constructor or destructor. Qualifiers are replaced immediately before and
-/// after the call so that qualified objects can be constructed with the same functions as unqualified objects.
-class ImplicitCtorDtorStmt : public Statement {
-  public:
-	// the constructor/destructor call statement; owned here for a while, eventually transferred elsewhere
-	Statement * callStmt;
-
-	ImplicitCtorDtorStmt( Statement * callStmt );
-	ImplicitCtorDtorStmt( const ImplicitCtorDtorStmt & other );
-	virtual ~ImplicitCtorDtorStmt();
-
-	Statement * get_callStmt() const { return callStmt; }
-	void set_callStmt( Statement * newValue ) { callStmt = newValue; }
-
-	virtual ImplicitCtorDtorStmt * clone() const override { return new ImplicitCtorDtorStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class MutexStmt : public Statement {
-  public:
-	Statement * stmt;
-	std::list<Expression *> mutexObjs; // list of mutex objects to acquire
-
-	MutexStmt( Statement * stmt, const std::list<Expression *> mutexObjs );
-	MutexStmt( const MutexStmt & other );
-	virtual ~MutexStmt();
-
-	virtual MutexStmt * clone() const override { return new MutexStmt( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,153 +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.
-//
-// SynTree.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Feb  1 09:22:33 2022
-// Update Count     : 14
-//
-
-#pragma once
-
-#include <string>
-#include <list>
-#include <map>
-#include <iostream>
-
-class BaseSyntaxNode;
-
-class Declaration;
-class DeclarationWithType;
-class ObjectDecl;
-class FunctionDecl;
-class AggregateDecl;
-class StructDecl;
-class UnionDecl;
-class EnumDecl;
-class TraitDecl;
-class NamedTypeDecl;
-class TypeDecl;
-class TypedefDecl;
-class AsmDecl;
-class DirectiveDecl;
-class StaticAssertDecl;
-class InlineMemberDecl;
-
-class Statement;
-class CompoundStmt;
-class ExprStmt;
-class AsmStmt;
-class DirectiveStmt;
-class IfStmt;
-class WhileDoStmt;
-class ForStmt;
-class SwitchStmt;
-class CaseStmt;
-class BranchStmt;
-class ReturnStmt;
-class ThrowStmt;
-class TryStmt;
-class CatchStmt;
-class FinallyStmt;
-class SuspendStmt;
-class WaitForStmt;
-class WithStmt;
-class NullStmt;
-class DeclStmt;
-class NullStmt;
-class ImplicitCtorDtorStmt;
-class MutexStmt;
-
-class Expression;
-class ApplicationExpr;
-class UntypedExpr;
-class NameExpr;
-class AddressExpr;
-class LabelAddressExpr;
-class CastExpr;
-class KeywordCastExpr;
-class VirtualCastExpr;
-class MemberExpr;
-class UntypedMemberExpr;
-class VariableExpr;
-class ConstantExpr;
-class SizeofExpr;
-class AlignofExpr;
-class UntypedOffsetofExpr;
-class OffsetofExpr;
-class OffsetPackExpr;
-class LogicalExpr;
-class ConditionalExpr;
-class CommaExpr;
-class TypeExpr;
-class DimensionExpr;
-class AsmExpr;
-class ImplicitCopyCtorExpr;
-class ConstructorExpr;
-class CompoundLiteralExpr;
-class RangeExpr;
-class UntypedTupleExpr;
-class TupleExpr;
-class TupleIndexExpr;
-class TupleAssignExpr;
-class StmtExpr;
-class UniqueExpr;
-class UntypedInitExpr;
-class InitExpr;
-class DeletedExpr;
-class DefaultArgExpr;
-class GenericExpr;
-class QualifiedNameExpr;
-
-class Type;
-class VoidType;
-class BasicType;
-class PointerType;
-class ArrayType;
-class ReferenceType;
-class QualifiedType;
-class FunctionType;
-class ReferenceToType;
-class StructInstType;
-class UnionInstType;
-class EnumInstType;
-class TraitInstType;
-class TypeInstType;
-class TupleType;
-class TypeofType;
-class VTableType;
-class AttrType;
-class VarArgsType;
-class ZeroType;
-class OneType;
-class GlobalScopeType;
-
-class Designation;
-class Initializer;
-class SingleInit;
-class ListInit;
-class ConstructorInit;
-
-//template <class T>	// emulate a union with templates?
-class Constant;
-
-// typedef std::string Label;
-class Label;
-typedef unsigned int UniqueId;
-
-class TypeSubstitution;
-
-// gcc attribute
-class Attribute;
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/TupleExpr.cc
===================================================================
--- src/SynTree/TupleExpr.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,136 +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.
-//
-// TupleExpr.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed Aug 14 14:34:00 2019
-// Update Count     : 5
-//
-
-#include <cassert>              // for assert, strict_dynamic_cast, assertf
-#include <iterator>             // for next
-#include <list>                 // for list, _List_iterator
-#include <ostream>              // for ostream, operator<<, basic_ostream, endl
-#include <string>               // for operator<<, string, char_traits
-
-#include "Common/utility.h"     // for cloneAll, deleteAll, printAll, toString
-#include "Declaration.h"        // for ObjectDecl
-#include "Expression.h"         // for Expression, TupleExpr, TupleIndexExpr
-#include "SynTree/Label.h"      // for Label
-#include "SynTree/Statement.h"  // for CompoundStmt, DeclStmt, ExprStmt, Sta...
-#include "Tuples/Tuples.h"      // for makeTupleType
-#include "Type.h"               // for TupleType, Type
-
-UntypedTupleExpr::UntypedTupleExpr( const std::list< Expression * > & exprs ) : Expression(), exprs( exprs ) {
-}
-
-UntypedTupleExpr::UntypedTupleExpr( const UntypedTupleExpr &other ) : Expression( other ) {
-	cloneAll( other.exprs, exprs );
-}
-
-UntypedTupleExpr::~UntypedTupleExpr() {
-	deleteAll( exprs );
-}
-
-void UntypedTupleExpr::print( std::ostream &os, Indenter indent ) const {
-	os << "Untyped Tuple:" << std::endl;
-	printAll( exprs, os, indent+1 );
-	Expression::print( os, indent );
-}
-
-TupleExpr::TupleExpr( const std::list< Expression * > & exprs ) : Expression(), exprs( exprs ) {
-	set_result( Tuples::makeTupleType( exprs ) );
-}
-
-TupleExpr::TupleExpr( const TupleExpr &other ) : Expression( other ) {
-	cloneAll( other.exprs, exprs );
-}
-
-TupleExpr::~TupleExpr() {
-	deleteAll( exprs );
-}
-
-bool TupleExpr::get_lvalue() const {
-	return false;
-}
-
-void TupleExpr::print( std::ostream &os, Indenter indent ) const {
-	os << "Tuple:" << std::endl;
-	printAll( exprs, os, indent+1 );
-	Expression::print( os, indent );
-}
-
-TupleIndexExpr::TupleIndexExpr( Expression * tuple, unsigned int index ) : tuple( tuple ), index( index )  {
-	TupleType * type = strict_dynamic_cast< TupleType * >( tuple->get_result() );
-	assertf( type->size() > index, "TupleIndexExpr index out of bounds: tuple size %d, requested index %d in expr %s", type->size(), index, toString( tuple ).c_str() );
-	set_result( (*std::next( type->get_types().begin(), index ))->clone() );
-}
-
-TupleIndexExpr::TupleIndexExpr( const TupleIndexExpr &other ) : Expression( other ), tuple( other.tuple->clone() ), index( other.index ) {
-}
-
-TupleIndexExpr::~TupleIndexExpr() {
-	delete tuple;
-}
-
-bool TupleIndexExpr::get_lvalue() const {
-	return tuple->get_lvalue();
-}
-
-void TupleIndexExpr::print( std::ostream &os, Indenter indent ) const {
-	os << "Tuple Index Expression, with tuple:" << std::endl;
-	os << indent+1;
-	tuple->print( os, indent+1 );
-	os << indent+1 << "with index: " << index << std::endl;
-	Expression::print( os, indent );
-}
-
-TupleAssignExpr::TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls ) : Expression() {
-	// convert internally into a StmtExpr which contains the declarations and produces the tuple of the assignments
-	set_result( Tuples::makeTupleType( assigns ) );
-	CompoundStmt * compoundStmt = new CompoundStmt();
-	std::list< Statement * > & stmts = compoundStmt->get_kids();
-	for ( ObjectDecl * obj : tempDecls ) {
-		stmts.push_back( new DeclStmt( obj ) );
-	}
-	TupleExpr * tupleExpr = new TupleExpr( assigns );
-	assert( tupleExpr->get_result() );
-	stmts.push_back( new ExprStmt( tupleExpr ) );
-	stmtExpr = new StmtExpr( compoundStmt );
-}
-
-TupleAssignExpr::TupleAssignExpr( const TupleAssignExpr &other ) : Expression( other ) {
-	assert( other.stmtExpr );
-	stmtExpr = other.stmtExpr->clone();
-}
-
-TupleAssignExpr::TupleAssignExpr( 
-	StmtExpr * s )
-: Expression(), stmtExpr(s) {
-}
-
-
-TupleAssignExpr::~TupleAssignExpr() {
-	delete stmtExpr;
-}
-
-void TupleAssignExpr::print( std::ostream &os, Indenter indent ) const {
-	os << "Tuple Assignment Expression, with stmt expr:" << std::endl;
-	os << indent+1;
-	stmtExpr->print( os, indent+1 );
-	Expression::print( os, indent );
-}
-
-
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/TupleType.cc
===================================================================
--- src/SynTree/TupleType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,60 +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.
-//
-// TupleType.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Dec 13 23:44:38 2019
-// Update Count     : 4
-//
-
-#include <list>                  // for list
-#include <ostream>               // for operator<<, ostream, basic_ostream
-
-#include "Common/utility.h"      // for cloneAll, deleteAll, printAll
-#include "Declaration.h"         // for Declaration, ObjectDecl
-#include "Initializer.h"         // for ListInit
-#include "LinkageSpec.h"         // for Cforall
-#include "Type.h"                // for TupleType, Type, Type::Qualifiers
-
-class Attribute;
-
-TupleType::TupleType( const Type::Qualifiers &tq, const std::list< Type * > & types, const std::list< Attribute * > & attributes ) : Type( tq, attributes ), types( types ) {
-	for ( Type * t : *this ) {
-		// xxx - this is very awkward. TupleTypes should contain objects so that members can be named, but if they don't have an initializer node then
-		// they end up getting constructors, which end up being inserted causing problems. This happens because the object decls have to be visited so that
-		// their types are kept in sync with the types list here. Ultimately, the types list here should be eliminated and perhaps replaced with a list-view
-		// of the object types list, but I digress. The temporary solution here is to make a ListInit with maybeConstructed = false, that way even when the
-		// object is visited, it is never constructed. Ultimately, a better solution might be either:
-		// a) to separate TupleType from its declarations, into TupleDecl and Tuple{Inst?}Type, ala StructDecl and StructInstType
-		// b) separate initializer nodes better, e.g. add a MaybeConstructed node that is replaced by genInit, rather than what currently exists in a bool
-		members.push_back( new ObjectDecl( "" , Type::StorageClasses(), LinkageSpec::Cforall, nullptr, t->clone(), new ListInit( {}, {}, false ) ) );
-	}
-}
-
-TupleType::TupleType( const TupleType& other ) : Type( other ) {
-	cloneAll( other.types, types );
-	cloneAll( other.members, members );
-}
-
-TupleType::~TupleType() {
-	deleteAll( types );
-	deleteAll( members );
-}
-
-void TupleType::print( std::ostream &os, Indenter indent ) const {
-	Type::print( os, indent );
-	os << "tuple of types" << std::endl;
-	printAll( types, os, indent+1 );
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,210 +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.
-//
-// Type.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed Jul 14 15:47:00 2021
-// Update Count     : 50
-//
-#include "Type.h"
-
-#include "Attribute.h"                // for Attribute
-#include "Common/ToString.hpp"        // for toCString
-#include "Common/utility.h"           // for cloneAll, deleteAll, printAll
-#include "InitTweak/InitTweak.h"      // for getPointerBase
-#include "SynTree/BaseSyntaxNode.h"   // for BaseSyntaxNode
-#include "SynTree/Declaration.h"      // for TypeDecl
-#include "SynTree/TypeSubstitution.h" // for TypeSubstitution
-
-using namespace std;
-
-// GENERATED START, DO NOT EDIT
-// GENERATED BY BasicTypes-gen.cc
-const char * BasicType::typeNames[] = {
-	"_Bool",
-	"char",
-	"signed char",
-	"unsigned char",
-	"signed short int",
-	"unsigned short int",
-	"signed int",
-	"unsigned int",
-	"signed long int",
-	"unsigned long int",
-	"signed long long int",
-	"unsigned long long int",
-	"__int128",
-	"unsigned __int128",
-	"_Float16",
-	"_Float16 _Complex",
-	"_Float32",
-	"_Float32 _Complex",
-	"float",
-	"float _Complex",
-	"_Float32x",
-	"_Float32x _Complex",
-	"_Float64",
-	"_Float64 _Complex",
-	"double",
-	"double _Complex",
-	"_Float64x",
-	"_Float64x _Complex",
-	"__float80",
-	"_Float128",
-	"_Float128 _Complex",
-	"__float128",
-	"long double",
-	"long double _Complex",
-	"_Float128x",
-	"_Float128x _Complex",
-};
-// GENERATED END
-
-Type::Type( const Qualifiers &tq, const std::list< Attribute * > & attributes ) : tq( tq ), attributes( attributes ) {}
-
-Type::Type( const Type &other ) : BaseSyntaxNode( other ), tq( other.tq ) {
-	cloneAll( other.forall, forall );
-	cloneAll( other.attributes, attributes );
-}
-
-Type::~Type() {
-	deleteAll( forall );
-	deleteAll( attributes );
-}
-
-// These must remain in the same order as the corresponding bit fields.
-const char * Type::FuncSpecifiersNames[] = { "inline", "_Noreturn", "fortran" };
-const char * Type::StorageClassesNames[] = { "extern", "static", "auto", "register", "__thread", "_Thread_local" };
-const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "mutex", "_Atomic" };
-
-Type * Type::stripDeclarator() {
-	Type * type, * at;
-	for ( type = this; (at = InitTweak::getPointerBase( type )); type = at );
-	return type;
-}
-
-Type * Type::stripReferences() {
-	Type * type;
-	ReferenceType * ref;
-	for ( type = this; (ref = dynamic_cast<ReferenceType *>( type )); type = ref->base );
-	return type;
-}
-
-const Type * Type::stripReferences() const {
-	const Type * type;
-	const ReferenceType * ref;
-	for ( type = this; (ref = dynamic_cast<const ReferenceType *>( type )); type = ref->base );
-	return type;
-}
-
-int Type::referenceDepth() const { return 0; }
-
-AggregateDecl * Type::getAggr() const {
-	assertf( false, "Non-aggregate type: %s", toCString( this ) );
-}
-
-TypeSubstitution Type::genericSubstitution() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
-
-void Type::print( std::ostream & os, Indenter indent ) const {
-	if ( ! forall.empty() ) {
-		os << "forall" << std::endl;
-		printAll( forall, os, indent+1 );
-		os << ++indent;
-	} // if
-
-	if ( ! attributes.empty() ) {
-		os << "with attributes" << endl;
-		printAll( attributes, os, indent+1 );
-	} // if
-
-	tq.print( os );
-}
-
-
-QualifiedType::QualifiedType( const Type::Qualifiers & tq, Type * parent, Type * child ) : Type( tq, {} ), parent( parent ), child( child ) {
-}
-
-QualifiedType::QualifiedType( const QualifiedType & other ) : Type( other ), parent( maybeClone( other.parent ) ), child( maybeClone( other.child ) ) {
-}
-
-QualifiedType::~QualifiedType() {
-	delete parent;
-	delete child;
-}
-
-void QualifiedType::print( std::ostream & os, Indenter indent ) const {
-	os << "Qualified Type:" << endl;
-	os << indent+1;
-	parent->print( os, indent+1 );
-	os << endl << indent+1;
-	child->print( os, indent+1 );
-	os << endl;
-	Type::print( os, indent+1 );
-}
-
-GlobalScopeType::GlobalScopeType() : Type( Type::Qualifiers(), {} ) {}
-
-void GlobalScopeType::print( std::ostream & os, Indenter ) const {
-	os << "Global Scope Type" << endl;
-}
-
-
-// Empty Variable declarations:
-const Type::FuncSpecifiers noFuncSpecifiers;
-const Type::StorageClasses noStorageClasses;
-const Type::Qualifiers noQualifiers;
-
-bool isUnboundType(const Type * type) {
-	if (auto typeInst = dynamic_cast<const TypeInstType *>(type)) {
-		// xxx - look for a type name produced by renameTyVars.
-
-		// TODO: once TypeInstType representation is updated, it should properly check
-		// if the context id is filled. this is a temporary hack for now
-		return isUnboundType(typeInst->name);
-	}
-	return false;
-}
-
-bool isUnboundType(const std::string & tname) {
-	// xxx - look for a type name produced by renameTyVars.
-
-	// TODO: once TypeInstType representation is updated, it should properly check
-	// if the context id is filled. this is a temporary hack for now
-	if (std::count(tname.begin(), tname.end(), '_') >= 3) {
-		return true;
-	}
-	return false;
-}
-
-VTableType::VTableType( const Type::Qualifiers &tq, Type *base, const std::list< Attribute * > & attributes )
-		: Type( tq, attributes ), base( base ) {
-	assertf( base, "VTableType with a null base created." );
-}
-
-VTableType::VTableType( const VTableType &other )
-		: Type( other ), base( other.base->clone() ) {
-}
-
-VTableType::~VTableType() {
-	delete base;
-}
-
-void VTableType::print( std::ostream &os, Indenter indent ) const {
-	Type::print( os, indent );
-	os << "get virtual-table type of ";
-	if ( base ) {
-		base->print( os, indent );
-	} // if
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,763 +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.
-//
-// Type.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Feb 19 22:37:10 2023
-// Update Count     : 176
-//
-
-#pragma once
-
-#include <strings.h>         // for ffs
-#include <cassert>           // for assert, assertf
-#include <list>              // for list, _List_iterator
-#include <ostream>           // for ostream, operator<<, basic_ostream
-#include <string>            // for string
-
-#include "BaseSyntaxNode.h"  // for BaseSyntaxNode
-#include "Common/Iterate.hpp"// for operator+
-#include "Mutator.h"         // for Mutator
-#include "SynTree.h"         // for AST nodes
-#include "Visitor.h"         // for Visitor
-
-class Type : public BaseSyntaxNode {
-  public:
-	// Simulate inheritance because union does not allow it.
-	// Bug in g++-4.9 prevents static field in union
-	//static const char * Names[];
-	#define BFCommon( BFType, N ) \
-		bool operator[]( unsigned int i ) const { return val & (1 << i); } \
-		bool any() const { return val != 0; } \
-		void reset() { val = 0; } \
-		int ffs() { return ::ffs( val ) - 1; } \
-		BFType operator&=( BFType other ) { \
-			val &= other.val; return *this; \
-		} \
-	 	BFType operator&( BFType other ) const { \
-			BFType q = other; \
-			q &= *this; \
-			return q; \
-		} \
-	 	BFType operator|=( BFType other ) { \
-			val |= other.val; return *this; \
-		} \
-	 	BFType operator|( BFType other ) const { \
-			BFType q = other; \
-			q |= *this; \
-			return q; \
-		} \
-	 	BFType operator-=( BFType other ) { \
-			val &= ~other.val; return *this; \
-		} \
-		void print( std::ostream & os ) const { \
-			if ( (*this).any() ) { \
-				for ( unsigned int i = 0; i < N; i += 1 ) { \
-					if ( (*this)[i] ) { \
-						os << BFType##Names[i] << ' '; \
-					} \
-				} \
-			} \
-		}
-
-	// enum must remain in the same order as the corresponding bit fields.
-
-	enum { Inline = 1 << 0, Noreturn = 1 << 1, Fortran = 1 << 2, NumFuncSpecifier = 3 };
-	static const char * FuncSpecifiersNames[];
-	union FuncSpecifiers {
-		unsigned int val;
-		struct {
-			bool is_inline : 1;
-			bool is_noreturn : 1;
-			bool is_fortran : 1;
-		};
-		FuncSpecifiers() : val( 0 ) {}
-		FuncSpecifiers( unsigned int val ) : val( val ) {}
-		// equality (==, !=) works implicitly on first field "val", relational operations are undefined.
-		BFCommon( FuncSpecifiers, NumFuncSpecifier )
-	}; // FuncSpecifiers
-
-	enum { Extern = 1 << 0, Static = 1 << 1, Auto = 1 << 2, Register = 1 << 3, ThreadlocalGcc = 1 << 4, ThreadlocalC11 = 1 << 5, NumStorageClass = 6 };
-	static const char * StorageClassesNames[];
-	union StorageClasses {
-		unsigned int val;
-		struct {
-			bool is_extern : 1;
-			bool is_static : 1;
-			bool is_auto : 1;
-			bool is_register : 1;
-			bool is_threadlocalGcc : 1;
-			bool is_threadlocalC11 : 1;
-		};
-
-		StorageClasses() : val( 0 ) {}
-		StorageClasses( unsigned int val ) : val( val ) {}
-		// equality (==, !=) works implicitly on first field "val", relational operations are undefined.
-		BFCommon( StorageClasses, NumStorageClass )
-
-		bool is_threadlocal_any() { return this->is_threadlocalC11 || this->is_threadlocalGcc; }
-	}; // StorageClasses
-
-	enum { Const = 1 << 0, Restrict = 1 << 1, Volatile = 1 << 2, Mutex = 1 << 3, Atomic = 1 << 4, NumTypeQualifier = 5 };
-	static const char * QualifiersNames[];
-	union Qualifiers {
-		enum { Mask = ~Restrict };
-		unsigned int val;
-		struct {
-			bool is_const : 1;
-			bool is_restrict : 1;
-			bool is_volatile : 1;
-			bool is_mutex : 1;
-			bool is_atomic : 1;
-		};
-
-		Qualifiers() : val( 0 ) {}
-		Qualifiers( unsigned int val ) : val( val ) {}
-		// Complex comparisons provide implicit qualifier downcasting, e.g., T downcast to const T.
-		bool operator==( Qualifiers other ) const { return (val & Mask) == (other.val & Mask); }
-		bool operator!=( Qualifiers other ) const { return (val & Mask) != (other.val & Mask); }
-		bool operator<=( Qualifiers other ) const {
-			return is_const    <= other.is_const        // Any non-const converts to const without cost
-				&& is_volatile <= other.is_volatile		// Any non-volatile converts to volatile without cost
-				&& is_mutex    >= other.is_mutex		// Any mutex converts to non-mutex without cost
-				&& is_atomic   == other.is_atomic;		// No conversion from atomic to non atomic is free
-		}
-		bool operator<( Qualifiers other ) const { return *this != other && *this <= other; }
-	 	bool operator>=( Qualifiers other ) const { return ! (*this < other); }
-	 	bool operator>( Qualifiers other ) const { return *this != other && *this >= other; }
-		BFCommon( Qualifiers, NumTypeQualifier )
-
-		Qualifiers unify( Qualifiers const & other ) const {
-			int or_flags = Mask & (val | other.val);
-			int and_flags = val & other.val;
-			return Qualifiers( or_flags | and_flags );
-		}
-	}; // Qualifiers
-
-	typedef std::list<TypeDecl *> ForallList;
-
-	Qualifiers tq;
-	ForallList forall;
-	std::list< Attribute * > attributes;
-
-	Type( const Qualifiers & tq, const std::list< Attribute * > & attributes );
-	Type( const Type & other );
-	virtual ~Type();
-
-	Qualifiers & get_qualifiers() { return tq; }
-	bool get_const() const { return tq.is_const; }
-	bool get_volatile() const { return tq.is_volatile; }
-	bool get_restrict() const { return tq.is_restrict; }
-	bool get_mutex() const { return tq.is_mutex; }
-	bool get_atomic() const { return tq.is_atomic; }
-	void set_const( bool newValue ) { tq.is_const = newValue; }
-	void set_volatile( bool newValue ) { tq.is_volatile = newValue; }
-	void set_restrict( bool newValue ) { tq.is_restrict = newValue; }
-	void set_mutex( bool newValue ) { tq.is_mutex = newValue; }
-	void set_atomic( bool newValue ) { tq.is_atomic = newValue; }
-
-	ForallList& get_forall() { return forall; }
-
-	std::list< Attribute * >& get_attributes() { return attributes; }
-	const std::list< Attribute * >& get_attributes() const { return attributes; }
-
-	/// How many elemental types are represented by this type
-	virtual unsigned size() const { return 1; };
-	virtual bool isVoid() const { return size() == 0; }
-	virtual Type * getComponent( unsigned i ) { assertf( size() == 1 && i == 0, "Type::getComponent was called with size %d and index %d\n", size(), i ); return this; }
-
-	/// return type without outer pointers and arrays
-	Type * stripDeclarator();
-
-	/// return type without outer references
-	Type * stripReferences();
-	const Type * stripReferences() const;
-
-	/// return the number of references occuring consecutively on the outermost layer of this type (i.e. do not count references nested within other types)
-	virtual int referenceDepth() const;
-
-	virtual bool isComplete() const { return true; }
-
-	virtual AggregateDecl * getAggr() const;
-
-	virtual TypeSubstitution genericSubstitution() const;
-
-	virtual Type * clone() const = 0;
-	virtual void accept( Visitor & v ) = 0;
-	virtual void accept( Visitor & v ) const = 0;
-	virtual Type * acceptMutator( Mutator & m ) = 0;
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
-};
-
-extern const Type::FuncSpecifiers noFuncSpecifiers;
-extern const Type::StorageClasses noStorageClasses;
-extern const Type::Qualifiers noQualifiers;			// no qualifiers on constants
-
-class VoidType : public Type {
-  public:
-	VoidType( const Type::Qualifiers & tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-
-	virtual unsigned size() const override { return 0; };
-	virtual bool isComplete() const override { return false; }
-
-	virtual VoidType * clone() const override { return new VoidType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class BasicType : public Type {
-  public:
-	// GENERATED START, DO NOT EDIT
-	// GENERATED BY BasicTypes-gen.cc
-	enum Kind {
-		Bool,
-		Char,
-		SignedChar,
-		UnsignedChar,
-		ShortSignedInt,
-		ShortUnsignedInt,
-		SignedInt,
-		UnsignedInt,
-		LongSignedInt,
-		LongUnsignedInt,
-		LongLongSignedInt,
-		LongLongUnsignedInt,
-		SignedInt128,
-		UnsignedInt128,
-		uFloat16,
-		uFloat16Complex,
-		uFloat32,
-		uFloat32Complex,
-		Float,
-		FloatComplex,
-		uFloat32x,
-		uFloat32xComplex,
-		uFloat64,
-		uFloat64Complex,
-		Double,
-		DoubleComplex,
-		uFloat64x,
-		uFloat64xComplex,
-		uuFloat80,
-		uFloat128,
-		uFloat128Complex,
-		uuFloat128,
-		LongDouble,
-		LongDoubleComplex,
-		uFloat128x,
-		uFloat128xComplex,
-		NUMBER_OF_BASIC_TYPES
-	} kind;
-	// GENERATED END
-
-	static const char * typeNames[];					// string names for basic types, MUST MATCH with Kind
-
-	BasicType( const Type::Qualifiers & tq, Kind bt, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-
-	Kind get_kind() const { return kind; }
-	void set_kind( Kind newValue ) { kind = newValue; }
-
-	virtual BasicType * clone() const override { return new BasicType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-	bool isInteger() const;
-};
-
-class PointerType : public Type {
-  public:
-	Type * base;
-
-	// In C99, pointer types can be qualified in many ways e.g., int f( int a[ static 3 ] )
-	Expression * dimension;
-	bool isVarLen;
-	bool isStatic;
-
-	PointerType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-	PointerType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-	PointerType( const PointerType& );
-	virtual ~PointerType();
-
-	Type * get_base() { return base; }
-	void set_base( Type * newValue ) { base = newValue; }
-	Expression * get_dimension() { return dimension; }
-	void set_dimension( Expression * newValue ) { dimension = newValue; }
-	bool get_isVarLen() { return isVarLen; }
-	void set_isVarLen( bool newValue ) { isVarLen = newValue; }
-	bool get_isStatic() { return isStatic; }
-	void set_isStatic( bool newValue ) { isStatic = newValue; }
-
-	bool is_array() const { return isStatic || isVarLen || dimension; }
-
-	virtual bool isComplete() const override { return ! isVarLen; }
-
-	virtual PointerType * clone() const override { return new PointerType( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class ArrayType : public Type {
-  public:
-	Type * base;
-	Expression * dimension;
-	bool isVarLen;
-	bool isStatic;
-
-	ArrayType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-	ArrayType( const ArrayType& );
-	virtual ~ArrayType();
-
-	Type * get_base() { return base; }
-	void set_base( Type * newValue ) { base = newValue; }
-	Expression * get_dimension() { return dimension; }
-	void set_dimension( Expression * newValue ) { dimension = newValue; }
-	bool get_isVarLen() { return isVarLen; }
-	void set_isVarLen( bool newValue ) { isVarLen = newValue; }
-	bool get_isStatic() { return isStatic; }
-	void set_isStatic( bool newValue ) { isStatic = newValue; }
-
-	// array types are complete if they have a dimension expression or are
-	// VLAs ('*' in parameter declaration), and incomplete otherwise.
-	// See 6.7.6.2
-	virtual bool isComplete() const override { return dimension || isVarLen; }
-
-	virtual ArrayType * clone() const override { return new ArrayType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class QualifiedType : public Type {
-public:
-	Type * parent;
-	Type * child;
-	QualifiedType( const Type::Qualifiers & tq, Type * parent, Type * child );
-	QualifiedType( const QualifiedType & tq );
-	virtual ~QualifiedType();
-
-	virtual QualifiedType * clone() const override { return new QualifiedType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class ReferenceType : public Type {
-public:
-	Type * base;
-
-	ReferenceType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-	ReferenceType( const ReferenceType & );
-	virtual ~ReferenceType();
-
-	Type * get_base() { return base; }
-	void set_base( Type * newValue ) { base = newValue; }
-
-	virtual int referenceDepth() const override;
-
-	// Since reference types act like value types, their size is the size of the base.
-	// This makes it simple to cast the empty tuple to a reference type, since casts that increase
-	// the number of values are disallowed.
-	virtual unsigned size() const override { return base->size(); }
-
-	virtual TypeSubstitution genericSubstitution() const override;
-
-	virtual ReferenceType * clone() const override { return new ReferenceType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class FunctionType : public Type {
-  public:
-	std::list<DeclarationWithType*> returnVals;
-	std::list<DeclarationWithType*> parameters;
-
-	// Does the function accept a variable number of arguments following the arguments specified in the parameters list.
-	// This could be because of
-	// - an ellipsis in a prototype declaration
-	// - an unprototyped declaration
-	bool isVarArgs;
-
-	FunctionType( const Type::Qualifiers & tq, bool isVarArgs, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-	FunctionType( const FunctionType& );
-	virtual ~FunctionType();
-
-	std::list<DeclarationWithType*> & get_returnVals() { return returnVals; }
-	std::list<DeclarationWithType*> & get_parameters() { return parameters; }
-	bool get_isVarArgs() const { return isVarArgs; }
-	void set_isVarArgs( bool newValue ) { isVarArgs = newValue; }
-	bool isTtype() const;
-
-	bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; }
-
-	virtual FunctionType * clone() const override { return new FunctionType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class ReferenceToType : public Type {
-  public:
-	std::list< Expression * > parameters;
-	std::string name;
-	bool hoistType;
-
-	ReferenceToType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes );
-	ReferenceToType( const ReferenceToType & other );
-	virtual ~ReferenceToType();
-
-	const std::string & get_name() const { return name; }
-	void set_name( std::string newValue ) { name = newValue; }
-	std::list< Expression* >& get_parameters() { return parameters; }
-	bool get_hoistType() const { return hoistType; }
-	void set_hoistType( bool newValue ) { hoistType = newValue; }
-
-	virtual ReferenceToType * clone() const override = 0;
-	virtual void accept( Visitor & v ) override = 0;
-	virtual Type * acceptMutator( Mutator & m ) override = 0;
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-
-	virtual void lookup( __attribute__((unused)) const std::string & name, __attribute__((unused)) std::list< Declaration* > & foundDecls ) const {}
-  protected:
-	virtual std::string typeString() const = 0;
-};
-
-class StructInstType : public ReferenceToType {
-	typedef ReferenceToType Parent;
-  public:
-	// this decl is not "owned" by the struct inst; it is merely a pointer to elsewhere in the tree,
-	// where the structure used in this type is actually defined
-	StructDecl * baseStruct;
-
-	StructInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ), baseStruct( 0 ) {}
-	StructInstType( const Type::Qualifiers & tq, StructDecl * baseStruct, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
-	StructInstType( const StructInstType & other ) : Parent( other ), baseStruct( other.baseStruct ) {}
-
-	StructDecl * get_baseStruct() const { return baseStruct; }
-	void set_baseStruct( StructDecl * newValue ) { baseStruct = newValue; }
-
-	/// Accesses generic parameters of base struct (NULL if none such)
-	std::list<TypeDecl*> * get_baseParameters();
-	const std::list<TypeDecl*> * get_baseParameters() const;
-
-	virtual bool isComplete() const override;
-
-	virtual AggregateDecl * getAggr() const override;
-
-	virtual TypeSubstitution genericSubstitution() const override;
-
-	/// Looks up the members of this struct named "name" and places them into "foundDecls".
-	/// Clones declarations into "foundDecls", caller responsible for freeing
-	void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override;
-
-	virtual StructInstType * clone() const override { return new StructInstType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-  private:
-	virtual std::string typeString() const override;
-};
-
-class UnionInstType : public ReferenceToType {
-	typedef ReferenceToType Parent;
-  public:
-	// this decl is not "owned" by the union inst; it is merely a pointer to elsewhere in the tree,
-	// where the union used in this type is actually defined
-	UnionDecl * baseUnion;
-
-	UnionInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ), baseUnion( 0 ) {}
-	UnionInstType( const Type::Qualifiers & tq, UnionDecl * baseUnion, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
-	UnionInstType( const UnionInstType & other ) : Parent( other ), baseUnion( other.baseUnion ) {}
-
-	UnionDecl * get_baseUnion() const { return baseUnion; }
-	void set_baseUnion( UnionDecl * newValue ) { baseUnion = newValue; }
-
-	/// Accesses generic parameters of base union (NULL if none such)
-	std::list<TypeDecl*> * get_baseParameters();
-	const std::list<TypeDecl*> * get_baseParameters() const;
-
-	virtual bool isComplete() const override;
-
-	virtual AggregateDecl * getAggr() const override;
-
-	virtual TypeSubstitution genericSubstitution() const override;
-
-	/// looks up the members of this union named "name" and places them into "foundDecls"
-	/// Clones declarations into "foundDecls", caller responsible for freeing
-	void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override;
-
-	virtual UnionInstType * clone() const override { return new UnionInstType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-  private:
-	virtual std::string typeString() const override;
-};
-
-class EnumInstType : public ReferenceToType {
-	typedef ReferenceToType Parent;
-  public:
-	// this decl is not "owned" by the enum inst; it is merely a pointer to elsewhere in the tree,
-	// where the enum used in this type is actually defined
-	EnumDecl * baseEnum = nullptr;
-
-	EnumInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ) {}
-	EnumInstType( const Type::Qualifiers & tq, EnumDecl * baseEnum, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
-	EnumInstType( const EnumInstType & other ) : Parent( other ), baseEnum( other.baseEnum ) {}
-
-	EnumDecl * get_baseEnum() const { return baseEnum; }
-	void set_baseEnum( EnumDecl * newValue ) { baseEnum = newValue; }
-
-	virtual bool isComplete() const override;
-
-	virtual AggregateDecl * getAggr() const override;
-
-	virtual EnumInstType * clone() const override { return new EnumInstType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-  private:
-	virtual std::string typeString() const override;
-};
-
-class TraitInstType : public ReferenceToType {
-	typedef ReferenceToType Parent;
-  public:
-	// this decl is not "owned" by the trait inst; it is merely a pointer to elsewhere in the tree,
-	// where the trait used in this type is actually defined
-	TraitDecl * baseTrait = nullptr;
-
-	TraitInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ) {}
-	TraitInstType( const Type::Qualifiers & tq, TraitDecl * baseTrait, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-	TraitInstType( const TraitInstType & other );
-	~TraitInstType();
-
-	virtual bool isComplete() const override;
-
-	virtual TraitInstType * clone() const override { return new TraitInstType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-  private:
-	virtual std::string typeString() const override;
-};
-
-class TypeInstType : public ReferenceToType {
-	typedef ReferenceToType Parent;
-  public:
-	// this decl is not "owned" by the type inst; it is merely a pointer to elsewhere in the tree,
-	// where the type used here is actually defined
-	TypeDecl * baseType;
-	bool isFtype;
-
-	TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl * baseType, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
-	TypeInstType( const Type::Qualifiers & tq, const std::string & name, bool isFtype, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
-	TypeInstType( const TypeInstType & other );
-	~TypeInstType();
-
-	TypeDecl * get_baseType() const { return baseType; }
-	void set_baseType( TypeDecl * newValue );
-	bool get_isFtype() const { return isFtype; }
-	void set_isFtype( bool newValue ) { isFtype = newValue; }
-
-	virtual bool isComplete() const override;
-
-	virtual TypeInstType * clone() const override { return new TypeInstType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-  private:
-	virtual std::string typeString() const override;
-};
-
-class TupleType : public Type {
-  public:
-	std::list<Type *> types;
-	std::list<Declaration *> members;
-
-	TupleType( const Type::Qualifiers & tq, const std::list< Type * > & types, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
-	TupleType( const TupleType& );
-	virtual ~TupleType();
-
-	typedef std::list<Type*> value_type;
-	typedef value_type::iterator iterator;
-
-	std::list<Type *> & get_types() { return types; }
-	virtual unsigned size() const override { return types.size(); };
-
-	// For now, this is entirely synthetic -- tuple types always have unnamed members.
-	// Eventually, we may allow named tuples, in which case members should subsume types
-	std::list<Declaration *> & get_members() { return members; }
-
-	iterator begin() { return types.begin(); }
-	iterator end() { return types.end(); }
-
-	virtual Type * getComponent( unsigned i ) override {
-		assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d", i, size() );
-		return *(begin()+i);
-	}
-
-	// virtual bool isComplete() const override { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness
-
-	virtual TupleType * clone() const override { return new TupleType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class TypeofType : public Type {
-  public:
-	Expression * expr;		///< expression to take the type of
-	bool is_basetypeof;		///< true iff is basetypeof type
-
-	TypeofType( const Type::Qualifiers & tq, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-	TypeofType( const Type::Qualifiers & tq, Expression * expr, bool is_basetypeof,
-		const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-	TypeofType( const TypeofType& );
-	virtual ~TypeofType();
-
-	Expression * get_expr() const { return expr; }
-	void set_expr( Expression * newValue ) { expr = newValue; }
-
-	virtual bool isComplete() const override { assert( false ); return false; }
-
-	virtual TypeofType * clone() const override { return new TypeofType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class VTableType : public Type {
-public:
-	Type * base;
-
-	VTableType( const Type::Qualifiers & tq, Type * base,
-		const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-	VTableType( const VTableType & );
-	virtual ~VTableType();
-
-	Type * get_base() { return base; }
-	void set_base( Type * newValue ) { base = newValue; }
-
-	virtual VTableType * clone() const override { return new VTableType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class AttrType : public Type {
-  public:
-	std::string name;
-	Expression * expr;
-	Type * type;
-	bool isType;
-
-	AttrType( const Type::Qualifiers & tq, const std::string & name, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-	AttrType( const Type::Qualifiers & tq, const std::string & name, Type * type, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
-	AttrType( const AttrType& );
-	virtual ~AttrType();
-
-	const std::string & get_name() const { return name; }
-	void set_name( const std::string & newValue ) { name = newValue; }
-	Expression * get_expr() const { return expr; }
-	void set_expr( Expression * newValue ) { expr = newValue; }
-	Type * get_type() const { return type; }
-	void set_type( Type * newValue ) { type = newValue; }
-	bool get_isType() const { return isType; }
-	void set_isType( bool newValue ) { isType = newValue; }
-
-	virtual bool isComplete() const override { assert( false ); } // xxx - not sure what to do here
-
-	virtual AttrType * clone() const override { return new AttrType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// Represents the GCC built-in varargs type
-class VarArgsType : public Type {
-  public:
-	VarArgsType();
-	VarArgsType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
-
-	virtual bool isComplete() const override{ return true; } // xxx - is this right?
-
-	virtual VarArgsType * clone() const override { return new VarArgsType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// Represents a zero constant
-class ZeroType : public Type {
-  public:
-	ZeroType();
-	ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
-
-	virtual ZeroType * clone() const override { return new ZeroType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-/// Represents a one constant
-class OneType : public Type {
-  public:
-	OneType();
-	OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
-
-	virtual OneType * clone() const override { return new OneType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-class GlobalScopeType : public Type {
-  public:
-	GlobalScopeType();
-
-	virtual GlobalScopeType * clone() const override { return new GlobalScopeType( *this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
-
-bool isUnboundType(const Type * type);
-bool isUnboundType(const std::string & tname);
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/TypeDecl.cc
===================================================================
--- src/SynTree/TypeDecl.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,64 +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.
-//
-// TypeDecl.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jan 12 16:07:33 2021
-// Update Count     : 26
-//
-
-#include <ostream>           // for ostream, operator<<, basic_ostream, basi...
-#include <string>            // for string, char_traits, operator+, operator<<
-
-#include "Common/utility.h"  // for maybeClone
-#include "Declaration.h"     // for TypeDecl, TypeDecl::Data, TypeDecl::Kind...
-#include "Type.h"            // for Type, Type::StorageClasses
-
-TypeDecl::TypeDecl( const std::string & name, Type::StorageClasses scs, Type * type, Kind kind, bool sized, Type * init ) :
-	Parent( name, scs, type ), kind( kind ), sized( kind == Ttype || sized ), init( init ) {
-}
-
-TypeDecl::TypeDecl( const TypeDecl & other ) : Parent( other ), kind( other.kind ), sized( other.sized ), init( maybeClone( other.init ) ) {
-}
-
-TypeDecl::~TypeDecl() {
-	delete init;
-}
-
-const char * TypeDecl::typeString() const {
-	static const char * kindNames[] = { "sized data type", "sized data type", "sized object type", "sized function type", "sized tuple type", "sized length value" };
-	static_assert( sizeof(kindNames) / sizeof(kindNames[0]) == TypeDecl::NUMBER_OF_KINDS, "typeString: kindNames is out of sync." );
-	assertf( kind < TypeDecl::NUMBER_OF_KINDS, "TypeDecl kind is out of bounds." );
-	return isComplete() ? kindNames[ kind ] : &kindNames[ kind ][ sizeof("sized") ]; // sizeof includes '\0'
-}
-
-const char * TypeDecl::genTypeString() const {
-	static const char * kindNames[] = { "T &", "T *", "T", "(*)", "T ...", "[T]" };
-	static_assert( sizeof(kindNames) / sizeof(kindNames[0]) == TypeDecl::NUMBER_OF_KINDS, "genTypeString: kindNames is out of sync." );
-	assertf( kind < TypeDecl::NUMBER_OF_KINDS, "TypeDecl kind is out of bounds." );
-	return kindNames[ kind ];
-}
-
-void TypeDecl::print( std::ostream &os, Indenter indent ) const {
-	NamedTypeDecl::print( os, indent );
-	if ( init ) {
-		os << std::endl << indent << "with type initializer: ";
-		init->print( os, indent + 1 );
-	} // if
-}
-
-std::ostream & operator<<( std::ostream & os, const TypeDecl::Data & data ) {
-	return os << data.kind << ", " << data.isComplete;
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/TypeExpr.cc
===================================================================
--- src/SynTree/TypeExpr.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,55 +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.
-//
-// TypeExpr.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon May 18 11:03:15 2015
-// Update Count     : 1
-//
-
-#include <iosfwd>            // for ostream
-
-#include "Common/utility.h"  // for maybeClone
-#include "Expression.h"      // for TypeExpr, Expression
-#include "Type.h"            // for Type
-
-TypeExpr::TypeExpr( Type *type ) : type( type ) {
-}
-
-TypeExpr::TypeExpr( const TypeExpr &other ) : Expression( other ), type( maybeClone( other.type ) ) {
-}
-
-TypeExpr::~TypeExpr() {
-	delete type;
-}
-
-void TypeExpr::print( std::ostream &os, Indenter indent ) const {
-	if ( type ) type->print( os, indent );
-	Expression::print( os, indent );
-}
-
-DimensionExpr::DimensionExpr( std::string name ) : Expression(), name(name) {
-	assertf(name != "0", "Zero is not a valid name");
-	assertf(name != "1", "One is not a valid name");
-}
-
-DimensionExpr::DimensionExpr( const DimensionExpr & other ) : Expression( other ), name( other.name ) {
-}
-
-DimensionExpr::~DimensionExpr() {}
-
-void DimensionExpr::print( std::ostream & os, Indenter indent ) const {
-	os << "Type-Sys Value: " << get_name();
-	Expression::print( os, indent );
-}
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/TypeSubstitution.cc
===================================================================
--- src/SynTree/TypeSubstitution.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,246 +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.
-//
-// TypeSubstitution.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 15:54:35 2017
-// Update Count     : 4
-//
-
-#include <ostream>  // for ostream, basic_ostream, operator<<, endl
-
-#include "Type.h"   // for TypeInstType, Type, StructInstType, UnionInstType
-#include "TypeSubstitution.h"
-
-TypeSubstitution::TypeSubstitution() {
-}
-
-TypeSubstitution::TypeSubstitution( const TypeSubstitution &other ) {
-	initialize( other, *this );
-}
-
-TypeSubstitution::~TypeSubstitution() {
-	for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
-		delete( i->second );
-	}
-	for ( VarEnvType::iterator i = varEnv.begin(); i != varEnv.end(); ++i ) {
-		delete( i->second );
-	}
-}
-
-TypeSubstitution &TypeSubstitution::operator=( const TypeSubstitution &other ) {
-	if ( this == &other ) return *this;
-	initialize( other, *this );
-	return *this;
-}
-
-void TypeSubstitution::initialize( const TypeSubstitution &src, TypeSubstitution &dest ) {
-	dest.typeEnv.clear();
-	dest.varEnv.clear();
-	dest.add( src );
-}
-
-void TypeSubstitution::add( const TypeSubstitution &other ) {
-	for ( TypeEnvType::const_iterator i = other.typeEnv.begin(); i != other.typeEnv.end(); ++i ) {
-		typeEnv[ i->first ] = i->second->clone();
-	} // for
-	for ( VarEnvType::const_iterator i = other.varEnv.begin(); i != other.varEnv.end(); ++i ) {
-		varEnv[ i->first ] = i->second->clone();
-	} // for
-}
-
-void TypeSubstitution::add( std::string formalType, Type *actualType ) {
-	TypeEnvType::iterator i = typeEnv.find( formalType );
-	if ( i != typeEnv.end() ) {
-		delete i->second;
-	} // if
-	typeEnv[ formalType ] = actualType->clone();
-}
-
-void TypeSubstitution::addVar( std::string formalExpr, Expression *actualExpr ) {
-	varEnv[ formalExpr ] = actualExpr;
-}
-
-void TypeSubstitution::remove( std::string formalType ) {
-	TypeEnvType::iterator i = typeEnv.find( formalType );
-	if ( i != typeEnv.end() ) {
-		delete i->second;
-		typeEnv.erase( formalType );
-	} // if
-}
-
-Type *TypeSubstitution::lookup( std::string formalType ) const {
-	TypeEnvType::const_iterator i = typeEnv.find( formalType );
-
-	// break on not in substitution set
-	if ( i == typeEnv.end() ) return 0;
-
-	// attempt to transitively follow TypeInstType links.
-	while ( TypeInstType *actualType = dynamic_cast< TypeInstType* >( i->second ) ) {
-		const std::string& typeName = actualType->get_name();
-
-		// break cycles in the transitive follow
-		if ( formalType == typeName ) break;
-
-		// Look for the type this maps to, returning previous mapping if none-such
-		i = typeEnv.find( typeName );
-		if ( i == typeEnv.end() ) return actualType;
-	}
-
-	// return type from substitution set
-	return i->second;
-
-#if 0
-	if ( i == typeEnv.end() ) {
-		return 0;
-	} else {
-		return i->second;
-	} // if
-#endif
-}
-
-bool TypeSubstitution::empty() const {
-	return typeEnv.empty() && varEnv.empty();
-}
-
-namespace {
-	struct EnvTrimmer {
-		const TypeSubstitution * env;
-		TypeSubstitution * newEnv;
-		EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
-		void previsit( TypeDecl * tyDecl ) {
-			// transfer known bindings for seen type variables
-			if ( Type * t = env->lookup( tyDecl->name ) ) {
-				newEnv->add( tyDecl->name, t );
-			}
-		}
-	};
-} // namespace
-
-/// reduce environment to just the parts that are referenced in a given expression
-TypeSubstitution * TypeSubstitution::newFromExpr( Expression * expr, const TypeSubstitution * env ) {
-	if ( env ) {
-		TypeSubstitution * newEnv = new TypeSubstitution();
-		PassVisitor<EnvTrimmer> trimmer( env, newEnv );
-		expr->accept( trimmer );
-		return newEnv;
-	}
-	return nullptr;
-}
-
-void TypeSubstitution::normalize() {
-	PassVisitor<Substituter> sub( *this, true );
-	do {
-		sub.pass.subCount = 0;
-		sub.pass.freeOnly = true;
-		for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
-			i->second = i->second->acceptMutator( sub );
-		}
-	} while ( sub.pass.subCount );
-}
-
-Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
-	BoundVarsType::const_iterator bound = boundVars.find( inst->name );
-	if ( bound != boundVars.end() ) return inst;
-
-	TypeEnvType::const_iterator i = sub.typeEnv.find( inst->get_name() );
-	if ( i == sub.typeEnv.end() ) {
-		return inst;
-	} else {
-		// cut off infinite loop for the case where a type is bound to itself.
-		// Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
-		// TODO: investigate preventing type variables from being bound to themselves in the first place.
-		if ( TypeInstType * replacement = dynamic_cast< TypeInstType * >( i->second ) ) {
-			if ( inst->name == replacement->name ) {
-				return inst;
-			}
-		}
-		// std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
-		subCount++;
-		Type * newtype = i->second->clone();
-		newtype->get_qualifiers() |= inst->get_qualifiers();
-		delete inst;
-		// Note: need to recursively apply substitution to the new type because normalize does not substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
-		return newtype->acceptMutator( *visitor );
-	} // if
-}
-
-Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) {
-	VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
-	if ( i == sub.varEnv.end() ) {
-		return nameExpr;
-	} else {
-		subCount++;
-		delete nameExpr;
-		return i->second->clone();
-	} // if
-}
-
-void TypeSubstitution::Substituter::premutate( Type * type ) {
-	GuardValue( boundVars );
-	// bind type variables from forall-qualifiers
-	if ( freeOnly ) {
-		for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
-			boundVars.insert( (*tyvar)->name );
-		} // for
-	} // if
-}
-
-template< typename TypeClass >
-void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
-	GuardValue( boundVars );
-	// bind type variables from forall-qualifiers
-	if ( freeOnly ) {
-		for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
-			boundVars.insert( (*tyvar)->name );
-		} // for
-		// bind type variables from generic type instantiations
-		std::list< TypeDecl* > *baseParameters = type->get_baseParameters();
-		if ( baseParameters && ! type->parameters.empty() ) {
-			for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) {
-				boundVars.insert( (*tyvar)->name );
-			} // for
-		} // if
-	} // if
-}
-
-void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) {
-	handleAggregateType( aggregateUseType );
-}
-
-void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
-	handleAggregateType( aggregateUseType );
-}
-
-void TypeSubstitution::print( std::ostream &os, Indenter indent ) const {
-	os << indent << "Types:" << std::endl;
-	for ( TypeEnvType::const_iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
-		os << indent+1 << i->first << " -> ";
-		i->second->print( os, indent+2 );
-		os << std::endl;
-	} // for
-	os << indent << "Non-types:" << std::endl;
-	for ( VarEnvType::const_iterator i = varEnv.begin(); i != varEnv.end(); ++i ) {
-		os << indent+1 << i->first << " -> ";
-		i->second->print( os, indent+2 );
-		os << std::endl;
-	} // for
-}
-
-std::ostream & operator<<( std::ostream & out, const TypeSubstitution & sub ) {
-	sub.print( out );
-	return out;
-}
-
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/TypeSubstitution.h
===================================================================
--- src/SynTree/TypeSubstitution.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,212 +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.
-//
-// TypeSubstitution.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Apr 30 22:52:47 2019
-// Update Count     : 9
-//
-
-#pragma once
-
-#include <cassert>                 // for assert
-#include <iosfwd>                  // for ostream
-#include <list>                    // for list<>::iterator, _List_iterator
-#include <unordered_map>
-#include <unordered_set>
-#include <string>                  // for string, operator!=
-#include <utility>                 // for pair
-
-#include "Common/SemanticError.h"  // for SemanticError
-#include "SynTree/Declaration.h"   // for TypeDecl, Declaration (ptr only)
-#include "SynTree/Expression.h"    // for Expression (ptr only), NameExpr (p...
-#include "SynTree/Type.h"          // for Type, ArrayType (ptr only), BasicT...
-
-class TypeSubstitution {
-  public:
-	TypeSubstitution();
-	template< typename FormalIterator, typename ActualIterator >
-	TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
-	TypeSubstitution( const TypeSubstitution &other );
-	virtual ~TypeSubstitution();
-
-	TypeSubstitution &operator=( const TypeSubstitution &other );
-
-	template< typename SynTreeClass > int apply( SynTreeClass *&input ) const;
-	template< typename SynTreeClass > int applyFree( SynTreeClass *&input ) const;
-
-	void add( std::string formalType, Type *actualType );
-	void add( const TypeSubstitution &other );
-	void remove( std::string formalType );
-	Type *lookup( std::string formalType ) const;
-	bool empty() const;
-
-	void addVar( std::string formalExpr, Expression *actualExpr );
-
-	template< typename FormalIterator, typename ActualIterator >
-	void add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
-
-	/// this function is unused...
-	template< typename TypeInstListIterator >
-	void extract( TypeInstListIterator begin, TypeInstListIterator end, TypeSubstitution &result );
-
-	/// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
-	static TypeSubstitution * newFromExpr( Expression * expr, const TypeSubstitution * env );
-
-	void normalize();
-
-	TypeSubstitution * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-
-	void print( std::ostream &os, Indenter indent = {} ) const;
-	TypeSubstitution *clone() const { return new TypeSubstitution( *this ); }
-  private:
-
-	// Mutator that performs the substitution
-	struct Substituter;
-
-	// TODO: worry about traversing into a forall-qualified function type or type decl with assertions
-
-	void initialize( const TypeSubstitution &src, TypeSubstitution &dest );
-
-	friend class Mutator;
-
-	template<typename pass_type>
-	friend class PassVisitor;
-
-	typedef std::unordered_map< std::string, Type * > TypeEnvType;
-	typedef std::unordered_map< std::string, Expression * > VarEnvType;
-	TypeEnvType typeEnv;
-	VarEnvType varEnv;
-
-  public:
-	// has to come after declaration of typeEnv
-	auto begin()       -> decltype( typeEnv.begin() ) { return typeEnv.begin(); }
-	auto   end()       -> decltype( typeEnv.  end() ) { return typeEnv.  end(); }
-	auto begin() const -> decltype( typeEnv.begin() ) { return typeEnv.begin(); }
-	auto   end() const -> decltype( typeEnv.  end() ) { return typeEnv.  end(); }
-
-	auto beginVar()       -> decltype( varEnv.begin() ) { return varEnv.begin(); }
-	auto   endVar()       -> decltype( varEnv.  end() ) { return varEnv.  end(); }
-	auto beginVar() const -> decltype( varEnv.begin() ) { return varEnv.begin(); }
-	auto   endVar() const -> decltype( varEnv.  end() ) { return varEnv.  end(); }
-};
-
-template< typename FormalIterator, typename ActualIterator >
-void TypeSubstitution::add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
-	// FormalIterator points to a TypeDecl
-	// ActualIterator points to a Type
-	FormalIterator formalIt = formalBegin;
-	ActualIterator actualIt = actualBegin;
-	for ( ; formalIt != formalEnd; ++formalIt, ++actualIt ) {
-		if ( TypeDecl *formal = dynamic_cast< TypeDecl * >( *formalIt ) ) {
-			if ( TypeExpr *actual = dynamic_cast< TypeExpr * >( *actualIt ) ) {
-				if ( formal->get_name() != "" ) {
-					TypeEnvType::iterator i = typeEnv.find( formal->get_name() );
-					if ( i != typeEnv.end() ) {
-						delete i->second;
-					} // if
-					typeEnv[ formal->get_name() ] = actual->get_type()->clone();
-				} // if
-			} else {
-				SemanticError( formal, toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ) );
-			} // if
-		} else {
-			// TODO: type check the formal and actual parameters
-			if ( (*formalIt)->get_name() != "" ) {
-				varEnv[ (*formalIt)->get_name() ] = (*actualIt)->clone();
-			} // if
-		} // if
-	} // for
-}
-
-template< typename FormalIterator, typename ActualIterator >
-TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
-	add( formalBegin, formalEnd, actualBegin );
-}
-
-// include needs to happen after TypeSubstitution is defined so that both TypeSubstitution and
-// PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.
-#include "Common/PassVisitor.h"
-
-// definitition must happen after PassVisitor is included so that WithGuards can be used
-struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> {
-		Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
-
-		Type * postmutate( TypeInstType * aggregateUseType );
-		Expression * postmutate( NameExpr * nameExpr );
-
-		/// Records type variable bindings from forall-statements
-		void premutate( Type * type );
-		/// Records type variable bindings from forall-statements and instantiations of generic types
-		template< typename TypeClass > void handleAggregateType( TypeClass * type );
-
-		void premutate( StructInstType * aggregateUseType );
-		void premutate( UnionInstType * aggregateUseType );
-
-		const TypeSubstitution & sub;
-		int subCount = 0;
-		bool freeOnly;
-		typedef std::unordered_set< std::string > BoundVarsType;
-		BoundVarsType boundVars;
-};
-
-template< typename SynTreeClass >
-int TypeSubstitution::apply( SynTreeClass *&input ) const {
-	assert( input );
-	PassVisitor<Substituter> sub( *this, false );
-	input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
-	assert( input );
-///	std::cerr << "substitution result is: ";
-///	newType->print( std::cerr );
-///	std::cerr << std::endl;
-	return sub.pass.subCount;
-}
-
-template< typename SynTreeClass >
-int TypeSubstitution::applyFree( SynTreeClass *&input ) const {
-	assert( input );
-	PassVisitor<Substituter> sub( *this, true );
-	input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
-	assert( input );
-///	std::cerr << "substitution result is: ";
-///	newType->print( std::cerr );
-///	std::cerr << std::endl;
-	return sub.pass.subCount;
-}
-
-template< typename TypeInstListIterator >
-void TypeSubstitution::extract( TypeInstListIterator begin, TypeInstListIterator end, TypeSubstitution &result ) {
-	// xxx - this function doesn't extract varEnv - is this intentional?
-	while ( begin != end ) {
-		TypeEnvType::iterator cur = typeEnv.find( (*begin++)->get_name() );
-		if ( cur != typeEnv.end() ) {
-			result.typeEnv[ cur->first ] = cur->second;
-			typeEnv.erase( cur );
-		} // if
-	} // while
-}
-
-/// Instantiate each member of the context given the actual parameters specified, and store the
-/// instantiations for use by the indexer
-template< typename FormalIterator, typename ActualIterator, typename MemberIterator, typename OutputIterator >
-void applySubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actual, MemberIterator memberBegin, MemberIterator memberEnd, OutputIterator out ) {
-	TypeSubstitution sub = TypeSubstitution( formalBegin, formalEnd, actual );
-	for ( auto i = memberBegin; i != memberEnd; ++i ) {
-		sub.apply( *i );
-		*out++ = *i;
-	} // for
-}
-
-std::ostream & operator<<( std::ostream & out, const TypeSubstitution & sub );
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/TypeofType.cc
===================================================================
--- src/SynTree/TypeofType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,53 +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.
-//
-// TypeofType.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  1 17:18:29 2017
-// Update Count     : 3
-//
-
-#include <list>              // for list
-#include <ostream>           // for operator<<, ostream
-
-#include "Common/utility.h"  // for maybeClone
-#include "Expression.h"      // for Expression
-#include "Type.h"            // for TypeofType, Type, Type::Qualifiers
-
-class Attribute;
-
-TypeofType::TypeofType( const Type::Qualifiers &tq, Expression *expr, 
-	const std::list< Attribute * > & attributes ) 
-: Type( tq, attributes ), expr( expr ), is_basetypeof(false) {}
-
-TypeofType::TypeofType( const Type::Qualifiers &tq, Expression *expr, bool is_basetypeof, 
-	const std::list< Attribute * > & attributes ) 
-: Type( tq, attributes ), expr( expr ), is_basetypeof( is_basetypeof ) {}
-
-TypeofType::TypeofType( const TypeofType &other )
-: Type( other ), expr( maybeClone( other.expr ) ), is_basetypeof( other.is_basetypeof ) {}
-
-TypeofType::~TypeofType() {
-	delete expr;
-}
-
-void TypeofType::print( std::ostream &os, Indenter indent ) const {
-	Type::print( os, indent );
-	if ( is_basetypeof ) { os << "base-"; }
-	os << "type-of expression ";
-	if ( expr ) {
-		expr->print( os, indent );
-	}
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/VarArgsType.cc
===================================================================
--- src/SynTree/VarArgsType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,36 +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.
-//
-// VarArgsType.cc --
-//
-// Author           : Aaron B. Moss
-// Created On       : Thu Feb 25 16:34:00 2016
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  1 17:14:48 2017
-// Update Count     : 4
-//
-
-#include <list>     // for list
-#include <ostream>  // for operator<<, ostream
-
-#include "Type.h"   // for Type, VarArgsType, Type::Qualifiers
-
-class Attribute;
-
-VarArgsType::VarArgsType() : Type( Type::Qualifiers(), std::list< Attribute * >() ) {}
-
-VarArgsType::VarArgsType( Type::Qualifiers tq, const std::list< Attribute * > & attributes ) : Type( tq, attributes ) {}
-
-void VarArgsType::print( std::ostream &os, Indenter indent ) const {
-	Type::print( os, indent );
-	os << "builtin var args pack";
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,287 +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.
-//
-// Visitor.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Feb  1 09:26:57 2022
-// Update Count     : 17
-//
-
-#pragma once
-
-#include "Common/SemanticError.h"  // for SemanticError
-#include "SynTree.h"               // for AST nodes
-
-class Visitor {
-  protected:
-	Visitor() = default;
-	virtual ~Visitor() = default;
-  public:
-	// visit: Default implementation of all functions visits the children
-	// of the given syntax node, but performs no other action.
-
-	virtual void visit( ObjectDecl * node ) { visit( const_cast<const ObjectDecl *>(node) ); }
-	virtual void visit( const ObjectDecl * objectDecl ) = 0;
-	virtual void visit( FunctionDecl * node ) { visit( const_cast<const FunctionDecl *>(node) ); }
-	virtual void visit( const FunctionDecl * functionDecl ) = 0;
-	virtual void visit( StructDecl * node ) { visit( const_cast<const StructDecl *>(node) ); }
-	virtual void visit( const StructDecl * aggregateDecl ) = 0;
-	virtual void visit( UnionDecl * node ) { visit( const_cast<const UnionDecl *>(node) ); }
-	virtual void visit( const UnionDecl * aggregateDecl ) = 0;
-	virtual void visit( EnumDecl * node ) { visit( const_cast<const EnumDecl *>(node) ); }
-	virtual void visit( const EnumDecl * aggregateDecl ) = 0;
-	virtual void visit( TraitDecl * node ) { visit( const_cast<const TraitDecl *>(node) ); }
-	virtual void visit( const TraitDecl * aggregateDecl ) = 0;
-	virtual void visit( TypeDecl * node ) { visit( const_cast<const TypeDecl *>(node) ); }
-	virtual void visit( const TypeDecl * typeDecl ) = 0;
-	virtual void visit( TypedefDecl * node ) { visit( const_cast<const TypedefDecl *>(node) ); }
-	virtual void visit( const TypedefDecl * typeDecl ) = 0;
-	virtual void visit( AsmDecl * node ) { visit( const_cast<const AsmDecl *>(node) ); }
-	virtual void visit( const AsmDecl * asmDecl ) = 0;
-	virtual void visit( DirectiveDecl * node ) { visit( const_cast<const DirectiveDecl *>(node) ); }
-	virtual void visit( const DirectiveDecl * directiveDecl ) = 0;
-	virtual void visit( StaticAssertDecl * node ) { visit( const_cast<const StaticAssertDecl *>(node) ); }
-	virtual void visit( const StaticAssertDecl * assertDecl ) = 0;
-	virtual void visit( InlineMemberDecl * node ) { visit( const_cast<const InlineMemberDecl *>(node) ); }
-	virtual void visit( const InlineMemberDecl * valueDecl ) = 0;
-
-	virtual void visit( CompoundStmt * node ) { visit( const_cast<const CompoundStmt *>(node) ); }
-	virtual void visit( const CompoundStmt * compoundStmt ) = 0;
-	virtual void visit( ExprStmt * node ) { visit( const_cast<const ExprStmt *>(node) ); }
-	virtual void visit( const ExprStmt * exprStmt ) = 0;
-	virtual void visit( AsmStmt * node ) { visit( const_cast<const AsmStmt *>(node) ); }
-	virtual void visit( const AsmStmt * asmStmt ) = 0;
-	virtual void visit( DirectiveStmt * node ) { visit( const_cast<const DirectiveStmt *>(node) ); }
-	virtual void visit( const DirectiveStmt * directiveStmt ) = 0;
-	virtual void visit( IfStmt * node ) { visit( const_cast<const IfStmt *>(node) ); }
-	virtual void visit( const IfStmt * ifStmt ) = 0;
-	virtual void visit( WhileDoStmt * node ) { visit( const_cast<const WhileDoStmt *>(node) ); }
-	virtual void visit( const WhileDoStmt * whileDoStmt ) = 0;
-	virtual void visit( ForStmt * node ) { visit( const_cast<const ForStmt *>(node) ); }
-	virtual void visit( const ForStmt * forStmt ) = 0;
-	virtual void visit( SwitchStmt * node ) { visit( const_cast<const SwitchStmt *>(node) ); }
-	virtual void visit( const SwitchStmt * switchStmt ) = 0;
-	virtual void visit( CaseStmt * node ) { visit( const_cast<const CaseStmt *>(node) ); }
-	virtual void visit( const CaseStmt * caseStmt ) = 0;
-	virtual void visit( BranchStmt * node ) { visit( const_cast<const BranchStmt *>(node) ); }
-	virtual void visit( const BranchStmt * branchStmt ) = 0;
-	virtual void visit( ReturnStmt * node ) { visit( const_cast<const ReturnStmt *>(node) ); }
-	virtual void visit( const ReturnStmt * returnStmt ) = 0;
-	virtual void visit( ThrowStmt * node ) { visit( const_cast<const ThrowStmt *>(node) ); }
-	virtual void visit( const ThrowStmt * throwStmt ) = 0;
-	virtual void visit( TryStmt * node ) { visit( const_cast<const TryStmt *>(node) ); }
-	virtual void visit( const TryStmt * tryStmt ) = 0;
-	virtual void visit( CatchStmt * node ) { visit( const_cast<const CatchStmt *>(node) ); }
-	virtual void visit( const CatchStmt * catchStmt ) = 0;
-	virtual void visit( FinallyStmt * node ) { visit( const_cast<const FinallyStmt *>(node) ); }
-	virtual void visit( const FinallyStmt * finallyStmt ) = 0;
-	virtual void visit( SuspendStmt * node ) { visit( const_cast<const SuspendStmt *>(node) ); }
-	virtual void visit( const SuspendStmt * suspendStmt ) = 0;
-	virtual void visit( WaitForStmt * node ) { visit( const_cast<const WaitForStmt *>(node) ); }
-	virtual void visit( const WaitForStmt * waitforStmt ) = 0;
-	virtual void visit( WithStmt * node ) { visit( const_cast<const WithStmt *>(node) ); }
-	virtual void visit( const WithStmt * withStmt ) = 0;
-	virtual void visit( NullStmt * node ) { visit( const_cast<const NullStmt *>(node) ); }
-	virtual void visit( const NullStmt * nullStmt ) = 0;
-	virtual void visit( DeclStmt * node ) { visit( const_cast<const DeclStmt *>(node) ); }
-	virtual void visit( const DeclStmt * declStmt ) = 0;
-	virtual void visit( ImplicitCtorDtorStmt * node ) { visit( const_cast<const ImplicitCtorDtorStmt *>(node) ); }
-	virtual void visit( const ImplicitCtorDtorStmt * impCtorDtorStmt ) = 0;
-	virtual void visit( MutexStmt * node ) { visit( const_cast<const MutexStmt *>(node) ); }
-	virtual void visit( const MutexStmt * mutexStmt ) = 0;
-
-	virtual void visit( ApplicationExpr * node ) { visit( const_cast<const ApplicationExpr *>(node) ); }
-	virtual void visit( const ApplicationExpr * applicationExpr ) = 0;
-	virtual void visit( UntypedExpr * node ) { visit( const_cast<const UntypedExpr *>(node) ); }
-	virtual void visit( const UntypedExpr * untypedExpr ) = 0;
-	virtual void visit( NameExpr * node ) { visit( const_cast<const NameExpr *>(node) ); }
-	virtual void visit( const NameExpr * nameExpr ) = 0;
-	virtual void visit( QualifiedNameExpr * node ) { visit( const_cast<const QualifiedNameExpr*>(node) );}
-	virtual void visit( const QualifiedNameExpr* qualifiednameExpr ) = 0;
-	virtual void visit( CastExpr * node ) { visit( const_cast<const CastExpr *>(node) ); }
-	virtual void visit( const CastExpr * castExpr ) = 0;
-	virtual void visit( KeywordCastExpr * node ) { visit( const_cast<const KeywordCastExpr *>(node) ); }
-	virtual void visit( const KeywordCastExpr * castExpr ) = 0;
-	virtual void visit( VirtualCastExpr * node ) { visit( const_cast<const VirtualCastExpr *>(node) ); }
-	virtual void visit( const VirtualCastExpr * castExpr ) = 0;
-	virtual void visit( AddressExpr * node ) { visit( const_cast<const AddressExpr *>(node) ); }
-	virtual void visit( const AddressExpr * addressExpr ) = 0;
-	virtual void visit( LabelAddressExpr * node ) { visit( const_cast<const LabelAddressExpr *>(node) ); }
-	virtual void visit( const LabelAddressExpr * labAddressExpr ) = 0;
-	virtual void visit( UntypedMemberExpr * node ) { visit( const_cast<const UntypedMemberExpr *>(node) ); }
-	virtual void visit( const UntypedMemberExpr * memberExpr ) = 0;
-	virtual void visit( MemberExpr * node ) { visit( const_cast<const MemberExpr *>(node) ); }
-	virtual void visit( const MemberExpr * memberExpr ) = 0;
-	virtual void visit( VariableExpr * node ) { visit( const_cast<const VariableExpr *>(node) ); }
-	virtual void visit( const VariableExpr * variableExpr ) = 0;
-	virtual void visit( ConstantExpr * node ) { visit( const_cast<const ConstantExpr *>(node) ); }
-	virtual void visit( const ConstantExpr * constantExpr ) = 0;
-	virtual void visit( SizeofExpr * node ) { visit( const_cast<const SizeofExpr *>(node) ); }
-	virtual void visit( const SizeofExpr * sizeofExpr ) = 0;
-	virtual void visit( AlignofExpr * node ) { visit( const_cast<const AlignofExpr *>(node) ); }
-	virtual void visit( const AlignofExpr * alignofExpr ) = 0;
-	virtual void visit( UntypedOffsetofExpr * node ) { visit( const_cast<const UntypedOffsetofExpr *>(node) ); }
-	virtual void visit( const UntypedOffsetofExpr * offsetofExpr ) = 0;
-	virtual void visit( OffsetofExpr * node ) { visit( const_cast<const OffsetofExpr *>(node) ); }
-	virtual void visit( const OffsetofExpr * offsetofExpr ) = 0;
-	virtual void visit( OffsetPackExpr * node ) { visit( const_cast<const OffsetPackExpr *>(node) ); }
-	virtual void visit( const OffsetPackExpr * offsetPackExpr ) = 0;
-	virtual void visit( LogicalExpr * node ) { visit( const_cast<const LogicalExpr *>(node) ); }
-	virtual void visit( const LogicalExpr * logicalExpr ) = 0;
-	virtual void visit( ConditionalExpr * node ) { visit( const_cast<const ConditionalExpr *>(node) ); }
-	virtual void visit( const ConditionalExpr * conditionalExpr ) = 0;
-	virtual void visit( CommaExpr * node ) { visit( const_cast<const CommaExpr *>(node) ); }
-	virtual void visit( const CommaExpr * commaExpr ) = 0;
-	virtual void visit( TypeExpr * node ) { visit( const_cast<const TypeExpr *>(node) ); }
-	virtual void visit( const TypeExpr * typeExpr ) = 0;
-	virtual void visit( DimensionExpr * node ) { visit( const_cast<const DimensionExpr *>(node) ); }
-	virtual void visit( const DimensionExpr * typeExpr ) = 0;
-	virtual void visit( AsmExpr * node ) { visit( const_cast<const AsmExpr *>(node) ); }
-	virtual void visit( const AsmExpr * asmExpr ) = 0;
-	virtual void visit( ImplicitCopyCtorExpr * node ) { visit( const_cast<const ImplicitCopyCtorExpr *>(node) ); }
-	virtual void visit( const ImplicitCopyCtorExpr * impCpCtorExpr ) = 0;
-	virtual void visit( ConstructorExpr * node ) { visit( const_cast<const ConstructorExpr *>(node) ); }
-	virtual void visit( const ConstructorExpr *  ctorExpr ) = 0;
-	virtual void visit( CompoundLiteralExpr * node ) { visit( const_cast<const CompoundLiteralExpr *>(node) ); }
-	virtual void visit( const CompoundLiteralExpr * compLitExpr ) = 0;
-	virtual void visit( RangeExpr * node ) { visit( const_cast<const RangeExpr *>(node) ); }
-	virtual void visit( const RangeExpr * rangeExpr ) = 0;
-	virtual void visit( UntypedTupleExpr * node ) { visit( const_cast<const UntypedTupleExpr *>(node) ); }
-	virtual void visit( const UntypedTupleExpr * tupleExpr ) = 0;
-	virtual void visit( TupleExpr * node ) { visit( const_cast<const TupleExpr *>(node) ); }
-	virtual void visit( const TupleExpr * tupleExpr ) = 0;
-	virtual void visit( TupleIndexExpr * node ) { visit( const_cast<const TupleIndexExpr *>(node) ); }
-	virtual void visit( const TupleIndexExpr * tupleExpr ) = 0;
-	virtual void visit( TupleAssignExpr * node ) { visit( const_cast<const TupleAssignExpr *>(node) ); }
-	virtual void visit( const TupleAssignExpr * assignExpr ) = 0;
-	virtual void visit( StmtExpr * node ) { visit( const_cast<const StmtExpr *>(node) ); }
-	virtual void visit( const StmtExpr *  stmtExpr ) = 0;
-	virtual void visit( UniqueExpr * node ) { visit( const_cast<const UniqueExpr *>(node) ); }
-	virtual void visit( const UniqueExpr *  uniqueExpr ) = 0;
-	virtual void visit( UntypedInitExpr * node ) { visit( const_cast<const UntypedInitExpr *>(node) ); }
-	virtual void visit( const UntypedInitExpr *  initExpr ) = 0;
-	virtual void visit( InitExpr * node ) { visit( const_cast<const InitExpr *>(node) ); }
-	virtual void visit( const InitExpr *  initExpr ) = 0;
-	virtual void visit( DeletedExpr * node ) { visit( const_cast<const DeletedExpr *>(node) ); }
-	virtual void visit( const DeletedExpr * delExpr ) = 0;
-	virtual void visit( DefaultArgExpr * node ) { visit( const_cast<const DefaultArgExpr *>(node) ); }
-	virtual void visit( const DefaultArgExpr * argExpr ) = 0;
-	virtual void visit( GenericExpr * node ) { visit( const_cast<const GenericExpr *>(node) ); }
-	virtual void visit( const GenericExpr * genExpr ) = 0;
-
-	virtual void visit( VoidType * node ) { visit( const_cast<const VoidType *>(node) ); }
-	virtual void visit( const VoidType * basicType ) = 0;
-	virtual void visit( BasicType * node ) { visit( const_cast<const BasicType *>(node) ); }
-	virtual void visit( const BasicType * basicType ) = 0;
-	virtual void visit( PointerType * node ) { visit( const_cast<const PointerType *>(node) ); }
-	virtual void visit( const PointerType * pointerType ) = 0;
-	virtual void visit( ArrayType * node ) { visit( const_cast<const ArrayType *>(node) ); }
-	virtual void visit( const ArrayType * arrayType ) = 0;
-	virtual void visit( ReferenceType * node ) { visit( const_cast<const ReferenceType *>(node) ); }
-	virtual void visit( const ReferenceType * refType ) = 0;
-	virtual void visit( QualifiedType * node ) { visit( const_cast<const QualifiedType *>(node) ); }
-	virtual void visit( const QualifiedType * qualType ) = 0;
-	virtual void visit( FunctionType * node ) { visit( const_cast<const FunctionType *>(node) ); }
-	virtual void visit( const FunctionType * functionType ) = 0;
-	virtual void visit( StructInstType * node ) { visit( const_cast<const StructInstType *>(node) ); }
-	virtual void visit( const StructInstType * aggregateUseType ) = 0;
-	virtual void visit( UnionInstType * node ) { visit( const_cast<const UnionInstType *>(node) ); }
-	virtual void visit( const UnionInstType * aggregateUseType ) = 0;
-	virtual void visit( EnumInstType * node ) { visit( const_cast<const EnumInstType *>(node) ); }
-	virtual void visit( const EnumInstType * aggregateUseType ) = 0;
-	virtual void visit( TraitInstType * node ) { visit( const_cast<const TraitInstType *>(node) ); }
-	virtual void visit( const TraitInstType * aggregateUseType ) = 0;
-	virtual void visit( TypeInstType * node ) { visit( const_cast<const TypeInstType *>(node) ); }
-	virtual void visit( const TypeInstType * aggregateUseType ) = 0;
-	virtual void visit( TupleType * node ) { visit( const_cast<const TupleType *>(node) ); }
-	virtual void visit( const TupleType * tupleType ) = 0;
-	virtual void visit( TypeofType * node ) { visit( const_cast<const TypeofType *>(node) ); }
-	virtual void visit( const TypeofType * typeofType ) = 0;
-	virtual void visit( VTableType * node ) { visit( const_cast<const VTableType *>(node) ); }
-	virtual void visit( const VTableType * vtableType ) = 0;
-	virtual void visit( AttrType * node ) { visit( const_cast<const AttrType *>(node) ); }
-	virtual void visit( const AttrType * attrType ) = 0;
-	virtual void visit( VarArgsType * node ) { visit( const_cast<const VarArgsType *>(node) ); }
-	virtual void visit( const VarArgsType * varArgsType ) = 0;
-	virtual void visit( ZeroType * node ) { visit( const_cast<const ZeroType *>(node) ); }
-	virtual void visit( const ZeroType * zeroType ) = 0;
-	virtual void visit( OneType * node ) { visit( const_cast<const OneType *>(node) ); }
-	virtual void visit( const OneType * oneType ) = 0;
-	virtual void visit( GlobalScopeType * node ) { visit( const_cast<const GlobalScopeType *>(node) ); }
-	virtual void visit( const GlobalScopeType * globalType ) = 0;
-
-	virtual void visit( Designation * node ) { visit( const_cast<const Designation *>(node) ); }
-	virtual void visit( const Designation * designation ) = 0;
-	virtual void visit( SingleInit * node ) { visit( const_cast<const SingleInit *>(node) ); }
-	virtual void visit( const SingleInit * singleInit ) = 0;
-	virtual void visit( ListInit * node ) { visit( const_cast<const ListInit *>(node) ); }
-	virtual void visit( const ListInit * listInit ) = 0;
-	virtual void visit( ConstructorInit * node ) { visit( const_cast<const ConstructorInit *>(node) ); }
-	virtual void visit( const ConstructorInit * ctorInit ) = 0;
-
-	virtual void visit( Constant * node ) { visit( const_cast<const Constant *>(node) ); }
-	virtual void visit( const Constant * constant ) = 0;
-
-	virtual void visit( Attribute * node ) { visit( const_cast<const Attribute *>(node) ); }
-	virtual void visit( const Attribute * attribute ) = 0;
-};
-
-template< typename TreeType, typename VisitorType >
-inline void maybeAccept( TreeType * tree, VisitorType & visitor ) {
-	if ( tree ) {
-		tree->accept( visitor );
-	}
-}
-
-template< typename TreeType, typename VisitorType >
-inline void maybeAccept( const TreeType * tree, VisitorType & visitor ) {
-	if ( tree ) {
-		tree->accept( visitor );
-	}
-}
-
-template< typename Container, typename VisitorType >
-inline void acceptAll( Container & container, VisitorType & visitor ) {
-	SemanticErrorException errors;
-	for ( auto * i : container ) {
-		try {
-			if ( i ) {
-				i->accept( visitor );
-			}
-		} catch( SemanticErrorException & e ) {
-			errors.append( e );
-		}
-	}
-	if ( ! errors.isEmpty() ) {
-		throw errors;
-	}
-}
-
-template< typename Container, typename VisitorType >
-inline void acceptAll( const Container & container, VisitorType & visitor ) {
-	SemanticErrorException errors;
-	for ( const auto * i : container ) {
-		try {
-			if ( i ) {
-				i->accept( visitor );
-			}
-		} catch( SemanticErrorException &e ) {
-			errors.append( e );
-		}
-	}
-	if ( ! errors.isEmpty() ) {
-		throw errors;
-	}
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/VoidType.cc
===================================================================
--- src/SynTree/VoidType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,35 +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.
-//
-// VoidType.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  1 17:09:26 2017
-// Update Count     : 3
-//
-
-#include <list>     // for list
-#include <ostream>  // for operator<<, ostream
-
-#include "Type.h"   // for VoidType, Type, Type::Qualifiers
-
-class Attribute;
-
-VoidType::VoidType( const Type::Qualifiers &tq, const std::list< Attribute * > & attributes ) : Type( tq, attributes ) {
-}
-
-void VoidType::print( std::ostream &os, Indenter indent ) const {
-	Type::print( os, indent );
-	os << "void ";
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/ZeroOneType.cc
===================================================================
--- src/SynTree/ZeroOneType.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,43 +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.
-//
-// VarArgsType.cc --
-//
-// Author           : Aaron B. Moss
-// Created On       : Fri Sep 16 14:08:00 2016
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  1 17:15:46 2017
-// Update Count     : 4
-//
-
-#include <list>     // for list
-#include <ostream>  // for operator<<, ostream
-
-#include "Type.h"   // for Type, Type::Qualifiers, OneType, ZeroType
-
-class Attribute;
-
-ZeroType::ZeroType() : Type( Type::Qualifiers(), std::list< Attribute * >() ) {}
-
-ZeroType::ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes ) : Type( tq, attributes ) {}
-
-void ZeroType::print( std::ostream &os, Indenter ) const {
-	os << "zero_t";
-}
-
-OneType::OneType() : Type( Type::Qualifiers(), std::list< Attribute * >() ) {}
-
-OneType::OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes ) : Type( tq, attributes ) {}
-
-void OneType::print( std::ostream &os, Indenter ) const {
-	os << "one_t";
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SynTree/module.mk
===================================================================
--- src/SynTree/module.mk	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,72 +1,0 @@
-######################### -*- Mode: Makefile-Gmake -*- ########################
-##
-## 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.
-##
-## module.mk --
-##
-## Author           : Richard C. Bilson
-## Created On       : Mon Jun  1 17:49:17 2015
-## Last Modified By : Peter A. Buhr
-## Last Modified On : Sat Dec 14 07:26:43 2019
-## Update Count     : 2
-###############################################################################
-
-SRC_SYNTREE = \
-      SynTree/AddressExpr.cc \
-      SynTree/AggregateDecl.cc \
-      SynTree/ApplicationExpr.cc \
-      SynTree/ArrayType.cc \
-      SynTree/Attribute.cc \
-      SynTree/Attribute.h \
-      SynTree/AttrType.cc \
-      SynTree/BaseSyntaxNode.h \
-      SynTree/BaseSyntaxNode.cc \
-      SynTree/BasicType.cc \
-      SynTree/CommaExpr.cc \
-      SynTree/CompoundStmt.cc \
-      SynTree/Constant.cc \
-      SynTree/Constant.h \
-      SynTree/Declaration.cc \
-      SynTree/Declaration.h \
-      SynTree/DeclarationWithType.cc \
-      SynTree/DeclReplacer.cc \
-      SynTree/DeclReplacer.h \
-      SynTree/DeclStmt.cc \
-      SynTree/Expression.cc \
-      SynTree/Expression.h \
-      SynTree/FunctionDecl.cc \
-      SynTree/FunctionType.cc \
-      SynTree/Initializer.cc \
-      SynTree/Initializer.h \
-      SynTree/InlineMemberDecl.cc \
-      SynTree/Label.h \
-      SynTree/LinkageSpec.cc \
-      SynTree/LinkageSpec.h \
-      SynTree/Mutator.h \
-      SynTree/NamedTypeDecl.cc \
-      SynTree/ObjectDecl.cc \
-      SynTree/PointerType.cc \
-      SynTree/ReferenceToType.cc \
-      SynTree/ReferenceType.cc \
-      SynTree/Statement.cc \
-      SynTree/Statement.h \
-      SynTree/SynTree.h \
-      SynTree/TupleExpr.cc \
-      SynTree/TupleType.cc \
-      SynTree/Type.cc \
-      SynTree/TypeDecl.cc \
-      SynTree/TypeExpr.cc \
-      SynTree/Type.h \
-      SynTree/TypeofType.cc \
-      SynTree/TypeSubstitution.cc \
-      SynTree/TypeSubstitution.h \
-      SynTree/VarArgsType.cc \
-      SynTree/Visitor.h \
-      SynTree/VoidType.cc \
-      SynTree/ZeroOneType.cc
-
-SRC += $(SRC_SYNTREE)
-SRCDEMANGLE += $(SRC_SYNTREE)
Index: src/Tuples/Explode.cc
===================================================================
--- src/Tuples/Explode.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Tuples/Explode.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -15,96 +15,8 @@
 
 #include "Explode.h"
-#include <list>                  // for list
 
 #include "AST/Pass.hpp"          // for Pass
-#include "SynTree/Mutator.h"     // for Mutator
-#include "Common/PassVisitor.h"  // for PassVisitor
 
 namespace Tuples {
-	namespace {
-		// remove one level of reference from a reference type -- may be useful elsewhere.
-		Type * getReferenceBase( Type * t ) {
-			if ( ReferenceType * refType = dynamic_cast<ReferenceType *>( t ) ) {
-				return refType->get_base();
-			} else {
-				// for the moment, I want to know immediately if a non-reference type is ever passed in here.
-				assertf( false, "getReferenceBase for non-ref: %s", toString( refType ).c_str() );
-				return nullptr;
-			}
-		}
-
-		struct CastExploder {
-			bool castAdded = false;
-			bool foundUniqueExpr = false;
-			Expression * applyCast( Expression * expr, bool first = true ) {
-				if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ){
-					foundUniqueExpr = true;
-					std::list< Expression * > exprs;
-					for ( Expression *& expr : tupleExpr->get_exprs() ) {
-						// move cast into tuple exprs
-						exprs.push_back( applyCast( expr, false ) );
-					}
-					// want the top-level expression to be cast to reference type, but not nested
-					// tuple expressions
-					if ( first ) {
-						castAdded = true;
-						Expression * tupleExpr = new TupleExpr( exprs );
-						return new CastExpr( tupleExpr, new ReferenceType( Type::Qualifiers(), tupleExpr->result->clone() ) );
-					} else {
-						return new TupleExpr( exprs );
-					}
-				}
-				if ( dynamic_cast<ReferenceType*>( expr->result ) ) {
-					// don't need to cast reference type to another reference type
-					return expr->clone();
-				} else {
-					// anything else should be cast to reference as normal
-					castAdded = true;
-					return new CastExpr( expr->clone(), new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );
-				}
-			}
-
-			Expression * postmutate( UniqueExpr * uniqueExpr ) {
-				// move cast into unique expr so that the unique expr has type T& rather than
-				// type T. In particular, this transformation helps with generating the
-				// correct code for reference-cast member tuple expressions, since the result
-				// should now be a tuple of references rather than a reference to a tuple.
-				// Still, this code is a bit awkward, and could use some improvement.
-				UniqueExpr * newUniqueExpr = new UniqueExpr( applyCast( uniqueExpr->get_expr() ), uniqueExpr->get_id() );
-				delete uniqueExpr;
-				if ( castAdded ) {
-					// if a cast was added by applyCast, then unique expr now has one more layer of reference
-					// than it had coming into this function. To ensure types still match correctly, need to cast
-					//  to reference base so that outer expressions are still correct.
-					castAdded = false;
-					Type * toType = getReferenceBase( newUniqueExpr->result );
-					return new CastExpr( newUniqueExpr, toType->clone() );
-				}
-				return newUniqueExpr;
-			}
-
-
-			Expression * postmutate( TupleIndexExpr * tupleExpr ) {
-				// tuple index expr needs to be rebuilt to ensure that the type of the
-				// field is consistent with the type of the tuple expr, since the field
-				// may have changed from type T to T&.
-				Expression * expr = tupleExpr->get_tuple();
-				tupleExpr->set_tuple( nullptr );
-				TupleIndexExpr * ret = new TupleIndexExpr( expr, tupleExpr->get_index() );
-				delete tupleExpr;
-				return ret;
-			}
-		};
-	} // namespace
-
-	Expression * distributeReference( Expression * expr ) {
-		PassVisitor<CastExploder> exploder;
-		expr = expr->acceptMutator( exploder );
-		if ( ! exploder.pass.foundUniqueExpr ) {
-			// if a UniqueExpr was found, then the cast has already been added inside the UniqueExpr as appropriate
-			expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );
-		}
-		return expr;
-	}
 
 namespace {
Index: src/Tuples/Explode.h
===================================================================
--- src/Tuples/Explode.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Tuples/Explode.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -20,10 +20,6 @@
 
 #include "AST/Expr.hpp"
-#include "ResolvExpr/Alternative.h"     // for Alternative, AltList
 #include "ResolvExpr/Candidate.hpp"     // for Candidate, CandidateList
-#include "ResolvExpr/ExplodedActual.h"  // for ExplodedActual
 #include "ResolvExpr/ExplodedArg.hpp"   // for ExplodedArg
-#include "SynTree/Expression.h"         // for Expression, UniqueExpr, AddressExpr
-#include "SynTree/Type.h"               // for TupleType, Type
 #include "Tuples.h"                     // for maybeImpure
 
@@ -32,109 +28,5 @@
 }
 
-namespace SymTab {
-class Indexer;
-}  // namespace SymTab
-
 namespace Tuples {
-	Expression * distributeReference( Expression * );
-
-	static inline CastExpr * isReferenceCast( Expression * expr ) {
-		if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
-			if ( dynamic_cast< ReferenceType * >( castExpr->result ) ) {
-				return castExpr;
-			}
-		}
-		return nullptr;
-	}
-
-	/// Append alternative to an OutputIterator of Alternatives
-	template<typename OutputIterator>
-	void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env,
-			const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need,
-			const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) {
-		*out++ = ResolvExpr::Alternative{ expr, env, openVars, need, cost, cvtCost };
-	}
-
-	/// Append alternative to an ExplodedActual
-	static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr,
-			const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&,
-			const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
-		ea.exprs.emplace_back( expr );
-		/// xxx -- merge environment, openVars, need, cost?
-	}
-
-	/// helper function used by explode
-	template< typename Output >
-	void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt,
-			const SymTab::Indexer & indexer, Output&& out, bool isTupleAssign ) {
-		if ( isTupleAssign ) {
-			// tuple assignment needs CastExprs to be recursively exploded to easily get at all of the components
-			if ( CastExpr * castExpr = isReferenceCast( expr ) ) {
-				ResolvExpr::AltList alts;
-				explodeUnique(
-					castExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign );
-				for ( ResolvExpr::Alternative & alt : alts ) {
-					// distribute reference cast over all components
-					append( std::forward<Output>(out), distributeReference( alt.release_expr() ),
-						alt.env, alt.openVars, alt.need, alt.cost, alt.cvtCost );
-				}
-				// in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives)
-				return;
-			}
-		}
-		Type * res = expr->get_result()->stripReferences();
-		if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) {
-			if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ) {
-				// can open tuple expr and dump its exploded components
-				for ( Expression * expr : tupleExpr->get_exprs() ) {
-					explodeUnique( expr, alt, indexer, std::forward<Output>(out), isTupleAssign );
-				}
-			} else {
-				// tuple type, but not tuple expr - recursively index into its components.
-				// if expr type is reference, convert to value type
-				Expression * arg = expr->clone();
-				if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
-					// expressions which may contain side effects require a single unique instance of the expression.
-					arg = new UniqueExpr( arg );
-				}
-				// cast reference to value type to facilitate further explosion
-				if ( dynamic_cast<ReferenceType *>( arg->get_result() ) ) {
-					arg = new CastExpr( arg, tupleType->clone() );
-				}
-				for ( unsigned int i = 0; i < tupleType->size(); i++ ) {
-					TupleIndexExpr * idx = new TupleIndexExpr( arg->clone(), i );
-					explodeUnique( idx, alt, indexer, std::forward<Output>(out), isTupleAssign );
-					delete idx;
-				}
-				delete arg;
-			}
-		} else {
-			// atomic (non-tuple) type - output a clone of the expression in a new alternative
-			append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need,
-				alt.cost, alt.cvtCost );
-		}
-	}
-
-	/// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type
-	template< typename Output >
-	void explode( const ResolvExpr::Alternative &alt, const SymTab::Indexer & indexer,
-			Output&& out, bool isTupleAssign = false ) {
-		explodeUnique( alt.expr, alt, indexer, std::forward<Output>(out), isTupleAssign );
-	}
-
-	// explode list of alternatives
-	template< typename AltIterator, typename Output >
-	void explode( AltIterator altBegin, AltIterator altEnd, const SymTab::Indexer & indexer,
-			Output&& out, bool isTupleAssign = false ) {
-		for ( ; altBegin != altEnd; ++altBegin ) {
-			explode( *altBegin, indexer, std::forward<Output>(out), isTupleAssign );
-		}
-	}
-
-	template< typename Output >
-	void explode( const ResolvExpr::AltList & alts, const SymTab::Indexer & indexer, Output&& out,
-			bool isTupleAssign = false ) {
-		explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign );
-	}
 
 const ast::Expr * distributeReference( const ast::Expr * );
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Tuples/TupleAssignment.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -28,5 +28,4 @@
 #include "AST/TypeEnvironment.hpp"
 #include "CodeGen/OperatorTable.h"
-#include "Common/PassVisitor.h"
 #include "Common/UniqueName.h"             // for UniqueName
 #include "Common/utility.h"                // for splice, zipWith
@@ -34,18 +33,7 @@
 #include "InitTweak/GenInit.h"             // for genCtorInit
 #include "InitTweak/InitTweak.h"           // for getPointerBase, isAssignment
-#include "ResolvExpr/Alternative.h"        // for AltList, Alternative
-#include "ResolvExpr/AlternativeFinder.h"  // for AlternativeFinder, simpleC...
 #include "ResolvExpr/Cost.h"               // for Cost
 #include "ResolvExpr/Resolver.h"           // for resolveCtorInit
-#include "ResolvExpr/TypeEnvironment.h"    // for TypeEnvironment
 #include "ResolvExpr/typeops.h"            // for combos
-#include "SynTree/LinkageSpec.h"           // for Cforall
-#include "SynTree/Declaration.h"           // for ObjectDecl
-#include "SynTree/Expression.h"            // for Expression, CastExpr, Name...
-#include "SynTree/Initializer.h"           // for ConstructorInit, SingleInit
-#include "SynTree/Statement.h"             // for ExprStmt
-#include "SynTree/Type.h"                  // for Type, Type::Qualifiers
-#include "SynTree/TypeSubstitution.h"      // for TypeSubstitution
-#include "SynTree/Visitor.h"               // for Visitor
 
 #if 0
@@ -56,330 +44,4 @@
 
 namespace Tuples {
-	class TupleAssignSpotter_old {
-	  public:
-		// dispatcher for Tuple (multiple and mass) assignment operations
-		TupleAssignSpotter_old( ResolvExpr::AlternativeFinder & );
-		void spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args );
-
-	  private:
-		void match();
-
-		struct Matcher {
-		  public:
-			Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
-				const ResolvExpr::AltList& rhs );
-			virtual ~Matcher() {}
-
-			virtual void match( std::list< Expression * > &out ) = 0;
-			ObjectDecl * newObject( UniqueName & namer, Expression * expr );
-
-			void combineState( const ResolvExpr::Alternative& alt ) {
-				compositeEnv.simpleCombine( alt.env );
-				ResolvExpr::mergeOpenVars( openVars, alt.openVars );
-				cloneAll( alt.need, need );
-			}
-
-			void combineState( const ResolvExpr::AltList& alts ) {
-				for ( const ResolvExpr::Alternative& alt : alts ) { combineState( alt ); }
-			}
-
-			ResolvExpr::AltList lhs, rhs;
-			TupleAssignSpotter_old &spotter;
-			ResolvExpr::Cost baseCost;
-			std::list< ObjectDecl * > tmpDecls;
-			ResolvExpr::TypeEnvironment compositeEnv;
-			ResolvExpr::OpenVarSet openVars;
-			ResolvExpr::AssertionSet need;
-		};
-
-		struct MassAssignMatcher : public Matcher {
-		  public:
-			MassAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
-				const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
-			virtual void match( std::list< Expression * > &out );
-		};
-
-		struct MultipleAssignMatcher : public Matcher {
-		  public:
-			MultipleAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
-				const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
-			virtual void match( std::list< Expression * > &out );
-		};
-
-		ResolvExpr::AlternativeFinder &currentFinder;
-		std::string fname;
-		std::unique_ptr< Matcher > matcher;
-	};
-
-	/// true if expr is an expression of tuple type
-	bool isTuple( Expression *expr ) {
-		if ( ! expr ) return false;
-		assert( expr->result );
-		return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() );
-	}
-
-	template< typename AltIter >
-	bool isMultAssign( AltIter begin, AltIter end ) {
-		// multiple assignment if more than one alternative in the range or if
-		// the alternative is a tuple
-		if ( begin == end ) return false;
-		if ( isTuple( begin->expr ) ) return true;
-		return ++begin != end;
-	}
-
-	bool refToTuple( Expression *expr ) {
-		assert( expr->get_result() );
-		// also check for function returning tuple of reference types
-		if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
-			return refToTuple( castExpr->get_arg() );
-		} else {
-			return isTuple( expr );
-		}
-		return false;
-	}
-
-	void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr,
-				std::vector<ResolvExpr::AlternativeFinder> &args ) {
-		TupleAssignSpotter_old spotter( currentFinder );
-		spotter.spot( expr, args );
-	}
-
-	TupleAssignSpotter_old::TupleAssignSpotter_old( ResolvExpr::AlternativeFinder &f )
-		: currentFinder(f) {}
-
-	void TupleAssignSpotter_old::spot( UntypedExpr * expr,
-			std::vector<ResolvExpr::AlternativeFinder> &args ) {
-		if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
-			if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {
-				fname = op->get_name();
-
-				// AlternativeFinder will naturally handle this case case, if it's legal
-				if ( args.size() == 0 ) return;
-
-				// if an assignment only takes 1 argument, that's odd, but maybe someone wrote
-				// the function, in which case AlternativeFinder will handle it normally
-				if ( args.size() == 1 && CodeGen::isAssignment( fname ) ) return;
-
-				// look over all possible left-hand-sides
-				for ( ResolvExpr::Alternative& lhsAlt : args[0] ) {
-					// skip non-tuple LHS
-					if ( ! refToTuple(lhsAlt.expr) ) continue;
-
-					// explode is aware of casts - ensure every LHS expression is sent into explode
-					// with a reference cast
-					// xxx - this seems to change the alternatives before the normal
-					//  AlternativeFinder flow; maybe this is desired?
-					if ( ! dynamic_cast<CastExpr*>( lhsAlt.expr ) ) {
-						lhsAlt.expr = new CastExpr( lhsAlt.expr,
-								new ReferenceType( Type::Qualifiers(),
-									lhsAlt.expr->result->clone() ) );
-					}
-
-					// explode the LHS so that each field of a tuple-valued-expr is assigned
-					ResolvExpr::AltList lhs;
-					explode( lhsAlt, currentFinder.get_indexer(), back_inserter(lhs), true );
-					for ( ResolvExpr::Alternative& alt : lhs ) {
-						// each LHS value must be a reference - some come in with a cast expression,
-						// if not just cast to reference here
-						if ( ! dynamic_cast<ReferenceType*>( alt.expr->get_result() ) ) {
-							alt.expr = new CastExpr( alt.expr,
-								new ReferenceType( Type::Qualifiers(),
-									alt.expr->get_result()->clone() ) );
-						}
-					}
-
-					if ( args.size() == 1 ) {
-						// mass default-initialization/destruction
-						ResolvExpr::AltList rhs{};
-						matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );
-						match();
-					} else if ( args.size() > 2 ) {
-						// expand all possible RHS possibilities
-						// TODO build iterative version of this instead of using combos
-						std::vector< ResolvExpr::AltList > rhsAlts;
-						combos( std::next(args.begin(), 1), args.end(),
-							std::back_inserter( rhsAlts ) );
-						for ( const ResolvExpr::AltList& rhsAlt : rhsAlts ) {
-							// multiple assignment
-							ResolvExpr::AltList rhs;
-							explode( rhsAlt, currentFinder.get_indexer(),
-								std::back_inserter(rhs), true );
-							matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );
-							match();
-						}
-					} else {
-						for ( const ResolvExpr::Alternative& rhsAlt : args[1] ) {
-							ResolvExpr::AltList rhs;
-							if ( isTuple(rhsAlt.expr) ) {
-								// multiple assignment
-								explode( rhsAlt, currentFinder.get_indexer(),
-									std::back_inserter(rhs), true );
-								matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );
-							} else {
-								// mass assignment
-								rhs.push_back( rhsAlt );
-								matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );
-							}
-							match();
-						}
-					}
-				}
-			}
-		}
-	}
-
-	void TupleAssignSpotter_old::match() {
-		assert ( matcher != 0 );
-
-		std::list< Expression * > new_assigns;
-		matcher->match( new_assigns );
-
-		if ( ! matcher->lhs.empty() || ! matcher->rhs.empty() ) {
-			// if both lhs and rhs are empty then this is the empty tuple case, wherein it's okay for new_assigns to be empty.
-			// if not the empty tuple case, return early so that no new alternatives are generated.
-			if ( new_assigns.empty() ) return;
-		}
-		ResolvExpr::AltList current;
-		// now resolve new assignments
-		for ( std::list< Expression * >::iterator i = new_assigns.begin();
-				i != new_assigns.end(); ++i ) {
-			PRINT(
-				std::cerr << "== resolving tuple assign ==" << std::endl;
-				std::cerr << *i << std::endl;
-			)
-
-			ResolvExpr::AlternativeFinder finder{ currentFinder.get_indexer(),
-				matcher->compositeEnv };
-
-			try {
-				finder.findWithAdjustment(*i);
-			} catch (...) {
-				return; // no match should not mean failure, it just means this particular tuple assignment isn't valid
-			}
-			// prune expressions that don't coincide with
-			ResolvExpr::AltList alts = finder.get_alternatives();
-			assert( alts.size() == 1 );
-			assert( alts.front().expr != 0 );
-			current.push_back( alts.front() );
-		}
-
-		// extract expressions from the assignment alternatives to produce a list of assignments
-		// that together form a single alternative
-		std::list< Expression *> solved_assigns;
-		for ( ResolvExpr::Alternative & alt : current ) {
-			solved_assigns.push_back( alt.expr->clone() );
-			matcher->combineState( alt );
-		}
-
-		// xxx -- was push_front
-		currentFinder.get_alternatives().push_back( ResolvExpr::Alternative{
-			new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv,
-			matcher->openVars,
-			ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ),
-			ResolvExpr::sumCost( current ) + matcher->baseCost } );
-	}
-
-	TupleAssignSpotter_old::Matcher::Matcher( TupleAssignSpotter_old &spotter,
-		const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs )
-	: lhs(lhs), rhs(rhs), spotter(spotter),
-	  baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
-		combineState( lhs );
-		combineState( rhs );
-	}
-
-	UntypedExpr * createFunc( const std::string &fname, ObjectDecl *left, ObjectDecl *right ) {
-		assert( left );
-		std::list< Expression * > args;
-		args.push_back( new VariableExpr( left ) );
-		// args.push_back( new AddressExpr( new VariableExpr( left ) ) );
-		if ( right ) args.push_back( new VariableExpr( right ) );
-		if ( left->type->referenceDepth() > 1 && CodeGen::isConstructor( fname ) ) {
-			args.front() = new AddressExpr( args.front() );
-			if ( right ) args.back() = new AddressExpr( args.back() );
-			return new UntypedExpr( new NameExpr( "?=?" ), args );
-		} else {
-			return new UntypedExpr( new NameExpr( fname ), args );
-		}
-	}
-
-	// removes environments from subexpressions within statement exprs, which could throw off later passes like those in Box which rely on PolyMutator, and adds the bindings to the compositeEnv
-	// xxx - maybe this should happen in alternative finder for every StmtExpr?
-	struct EnvRemover {
-		void previsit( ExprStmt * stmt ) {
-			assert( compositeEnv );
-			if ( stmt->expr->env ) {
-				compositeEnv->add( *stmt->expr->env );
-				delete stmt->expr->env;
-				stmt->expr->env = nullptr;
-			}
-		}
-
-		ResolvExpr::TypeEnvironment * compositeEnv = nullptr;
-	};
-
-	ObjectDecl * TupleAssignSpotter_old::Matcher::newObject( UniqueName & namer, Expression * expr ) {
-		assert( expr->result && ! expr->get_result()->isVoid() );
-		ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->result->clone(), new SingleInit( expr->clone() ) );
-		// if expression type is a reference, don't need to construct anything, a simple initializer is sufficient.
-		if ( ! dynamic_cast< ReferenceType * >( expr->result ) ) {
-			ConstructorInit * ctorInit = InitTweak::genCtorInit( ret );
-			ret->init = ctorInit;
-			ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
-			PassVisitor<EnvRemover> rm; // remove environments from subexpressions of StmtExprs
-			rm.pass.compositeEnv = &compositeEnv;
-			ctorInit->accept( rm );
-		}
-		PRINT( std::cerr << "new object: " << ret << std::endl; )
-		return ret;
-	}
-
-	void TupleAssignSpotter_old::MassAssignMatcher::match( std::list< Expression * > &out ) {
-		static UniqueName lhsNamer( "__massassign_L" );
-		static UniqueName rhsNamer( "__massassign_R" );
-		// empty tuple case falls into this matcher, hence the second part of the assert
-		assert( (! lhs.empty() && rhs.size() <= 1) || (lhs.empty() && rhs.empty()) );
-
-		// xxx - may need to split this up into multiple declarations, because potential conversion to references
-		//  probably should not reference local variable - see MultipleAssignMatcher::match
-		ObjectDecl * rtmp = rhs.size() == 1 ? newObject( rhsNamer, rhs.front().expr ) : nullptr;
-		for ( ResolvExpr::Alternative & lhsAlt : lhs ) {
-			// create a temporary object for each value in the lhs and create a call involving the rhs
-			ObjectDecl * ltmp = newObject( lhsNamer, lhsAlt.expr );
-			out.push_back( createFunc( spotter.fname, ltmp, rtmp ) );
-			tmpDecls.push_back( ltmp );
-		}
-		if ( rtmp ) tmpDecls.push_back( rtmp );
-	}
-
-	void TupleAssignSpotter_old::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
-		static UniqueName lhsNamer( "__multassign_L" );
-		static UniqueName rhsNamer( "__multassign_R" );
-
-		if ( lhs.size() == rhs.size() ) {
-			// produce a new temporary object for each value in the lhs and rhs and pairwise create the calls
-			std::list< ObjectDecl * > ltmp;
-			std::list< ObjectDecl * > rtmp;
-			for ( auto p : group_iterate( lhs, rhs ) ) {
-				ResolvExpr::Alternative & lhsAlt = std::get<0>(p);
-				ResolvExpr::Alternative & rhsAlt = std::get<1>(p);
-				// convert RHS to LHS type minus one reference -- important for the case where LHS is && and RHS is lvalue, etc.
-				ReferenceType * lhsType = strict_dynamic_cast<ReferenceType *>( lhsAlt.expr->result );
-				rhsAlt.expr = new CastExpr( rhsAlt.expr, lhsType->base->clone() );
-				ObjectDecl * lobj = newObject( lhsNamer, lhsAlt.expr );
-				ObjectDecl * robj = newObject( rhsNamer, rhsAlt.expr );
-				out.push_back( createFunc(spotter.fname, lobj, robj) );
-				ltmp.push_back( lobj );
-				rtmp.push_back( robj );
-
-				// resolve the cast expression so that rhsAlt return type is bound by the cast type as needed, and transfer the resulting environment
-				ResolvExpr::AlternativeFinder finder{ spotter.currentFinder.get_indexer(), compositeEnv };
-				finder.findWithAdjustment( rhsAlt.expr );
-				assert( finder.get_alternatives().size() == 1 );
-				compositeEnv = std::move( finder.get_alternatives().front().env );
-			}
-			tmpDecls.splice( tmpDecls.end(), ltmp );
-			tmpDecls.splice( tmpDecls.end(), rtmp );
-		}
-	}
 
 namespace {
@@ -403,9 +65,9 @@
 
 	/// Dispatcher for tuple (multiple and mass) assignment operations
-	class TupleAssignSpotter_new final {
+	class TupleAssignSpotter final {
 		/// Actually finds tuple assignment operations, by subclass
 		struct Matcher {
 			ResolvExpr::CandidateList lhs, rhs;
-			TupleAssignSpotter_new & spotter;
+			TupleAssignSpotter & spotter;
 			CodeLocation location;
 			ResolvExpr::Cost baseCost;
@@ -422,5 +84,5 @@
 
 			Matcher(
-				TupleAssignSpotter_new & s, const CodeLocation & loc,
+				TupleAssignSpotter & s, const CodeLocation & loc,
 				const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
 			: lhs( l ), rhs( r ), spotter( s ), location( loc ),
@@ -499,5 +161,5 @@
 		struct MassAssignMatcher final : public Matcher {
 			MassAssignMatcher(
-				TupleAssignSpotter_new & s, const CodeLocation & loc,
+				TupleAssignSpotter & s, const CodeLocation & loc,
 				const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
 			: Matcher( s, loc, l, r ) {}
@@ -529,5 +191,5 @@
 		struct MultipleAssignMatcher final : public Matcher {
 			MultipleAssignMatcher(
-				TupleAssignSpotter_new & s, const CodeLocation & loc,
+				TupleAssignSpotter & s, const CodeLocation & loc,
 				const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
 			: Matcher( s, loc, l, r ) {}
@@ -578,5 +240,5 @@
 
 	public:
-		TupleAssignSpotter_new( ResolvExpr::CandidateFinder & f )
+		TupleAssignSpotter( ResolvExpr::CandidateFinder & f )
 		: crntFinder( f ), fname(), matcher() {}
 
@@ -715,5 +377,5 @@
 	std::vector< ResolvExpr::CandidateFinder > & args
 ) {
-	TupleAssignSpotter_new spotter{ finder };
+	TupleAssignSpotter spotter{ finder };
 	spotter.spot( assign, args );
 }
Index: src/Tuples/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Tuples/TupleExpansion.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -23,300 +23,11 @@
 #include "AST/Node.hpp"
 #include "AST/Type.hpp"
-#include "Common/PassVisitor.h"   // for PassVisitor, WithDeclsToAdd, WithGu...
 #include "Common/ScopedMap.h"     // for ScopedMap
 #include "Common/utility.h"       // for CodeLocation
 #include "InitTweak/InitTweak.h"  // for getFunction
-#include "SynTree/LinkageSpec.h"  // for Spec, C, Intrinsic
-#include "SynTree/Constant.h"     // for Constant
-#include "SynTree/Declaration.h"  // for StructDecl, DeclarationWithType
-#include "SynTree/Expression.h"   // for UntypedMemberExpr, Expression, Uniq...
-#include "SynTree/Label.h"        // for operator==, Label
-#include "SynTree/Mutator.h"      // for Mutator
-#include "SynTree/Type.h"         // for Type, Type::Qualifiers, TupleType
-#include "SynTree/Visitor.h"      // for Visitor
 #include "Tuples.h"
 
-class CompoundStmt;
-class TypeSubstitution;
+namespace Tuples {
 
-namespace Tuples {
-	namespace {
-		struct MemberTupleExpander final : public WithShortCircuiting, public WithVisitorRef<MemberTupleExpander> {
-			void premutate( UntypedMemberExpr * ) { visit_children = false; }
-			Expression * postmutate( UntypedMemberExpr * memberExpr );
-		};
-
-		struct UniqueExprExpander final : public WithDeclsToAdd {
-			Expression * postmutate( UniqueExpr * unqExpr );
-
-			std::map< int, Expression * > decls; // not vector, because order added may not be increasing order
-
-			~UniqueExprExpander() {
-				for ( std::pair<const int, Expression *> & p : decls ) {
-					delete p.second;
-				}
-			}
-		};
-
-		struct TupleAssignExpander {
-			Expression * postmutate( TupleAssignExpr * tupleExpr );
-		};
-
-		struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public WithConstTypeSubstitution {
-			Type * postmutate( TupleType * tupleType );
-
-			void premutate( CompoundStmt * ) {
-				GuardScope( typeMap );
-			}
-		  private:
-			ScopedMap< int, StructDecl * > typeMap;
-		};
-
-		struct TupleIndexExpander {
-			Expression * postmutate( TupleIndexExpr * tupleExpr );
-		};
-
-		struct TupleExprExpander final {
-			Expression * postmutate( TupleExpr * tupleExpr );
-		};
-	}
-
-	void expandMemberTuples( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<MemberTupleExpander> expander;
-		mutateAll( translationUnit, expander );
-	}
-
-	void expandUniqueExpr( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<UniqueExprExpander> unqExpander;
-		mutateAll( translationUnit, unqExpander );
-	}
-
-	void expandTuples( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<TupleAssignExpander> assnExpander;
-		mutateAll( translationUnit, assnExpander );
-
-		PassVisitor<TupleTypeReplacer> replacer;
-		mutateAll( translationUnit, replacer );
-
-		PassVisitor<TupleIndexExpander> idxExpander;
-		mutateAll( translationUnit, idxExpander );
-
-		PassVisitor<TupleExprExpander> exprExpander;
-		mutateAll( translationUnit, exprExpander );
-	}
-
-	namespace {
-		/// given a expression representing the member and an expression representing the aggregate,
-		/// reconstructs a flattened UntypedMemberExpr with the right precedence
-		Expression * reconstructMemberExpr( Expression * member, Expression * aggr, CodeLocation & loc ) {
-			if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( member ) ) {
-				// construct a new UntypedMemberExpr with the correct structure , and recursively
-				// expand that member expression.
-				PassVisitor<MemberTupleExpander> expander;
-				UntypedMemberExpr * inner = new UntypedMemberExpr( memberExpr->aggregate, aggr->clone() );
-				UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->member, inner );
-				inner->location = newMemberExpr->location = loc;
-				memberExpr->member = nullptr;
-				memberExpr->aggregate = nullptr;
-				delete memberExpr;
-				return newMemberExpr->acceptMutator( expander );
-			} else {
-				// not a member expression, so there is nothing to do but attach and return
-				UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( member, aggr->clone() );
-				newMemberExpr->location = loc;
-				return newMemberExpr;
-			}
-		}
-	}
-
-	Expression * MemberTupleExpander::postmutate( UntypedMemberExpr * memberExpr ) {
-		if ( UntypedTupleExpr * tupleExpr = dynamic_cast< UntypedTupleExpr * > ( memberExpr->member ) ) {
-			Expression * aggr = memberExpr->aggregate->clone()->acceptMutator( *visitor );
-			// aggregate expressions which might be impure must be wrapped in unique expressions
-			if ( Tuples::maybeImpureIgnoreUnique( memberExpr->aggregate ) ) aggr = new UniqueExpr( aggr );
-			for ( Expression *& expr : tupleExpr->exprs ) {
-				expr = reconstructMemberExpr( expr, aggr, memberExpr->location );
-				expr->location = memberExpr->location;
-			}
-			delete aggr;
-			tupleExpr->location = memberExpr->location;
-			return tupleExpr;
-		} else {
-			// there may be a tuple expr buried in the aggregate
-			// xxx - this is a memory leak
-			UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->member->clone(), memberExpr->aggregate->acceptMutator( *visitor ) );
-			newMemberExpr->location = memberExpr->location;
-			return newMemberExpr;
-		}
-	}
-
-	Expression * UniqueExprExpander::postmutate( UniqueExpr * unqExpr ) {
-		const int id = unqExpr->get_id();
-
-		// on first time visiting a unique expr with a particular ID, generate the expression that replaces all UniqueExprs with that ID,
-		// and lookup on subsequent hits. This ensures that all unique exprs with the same ID reference the same variable.
-		if ( ! decls.count( id ) ) {
-			Expression * assignUnq;
-			Expression * var = unqExpr->get_var();
-			if ( unqExpr->get_object() ) {
-				// an object was generated to represent this unique expression -- it should be added to the list of declarations now
-				declsToAddBefore.push_back( unqExpr->get_object() );
-				unqExpr->set_object( nullptr );
-				// steal the expr from the unqExpr
-				assignUnq = UntypedExpr::createAssign( unqExpr->get_var()->clone(), unqExpr->get_expr() );
-				unqExpr->set_expr( nullptr );
-			} else {
-				// steal the already generated assignment to var from the unqExpr - this has been generated by FixInit
-				Expression * expr = unqExpr->get_expr();
-				CommaExpr * commaExpr = strict_dynamic_cast< CommaExpr * >( expr );
-				assignUnq = commaExpr->get_arg1();
-				commaExpr->set_arg1( nullptr );
-			}
-			ObjectDecl * finished = new ObjectDecl( toString( "_unq", id, "_finished_" ), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::Bool ),
-													new SingleInit( new ConstantExpr( Constant::from_int( 0 ) ) ) );
-			declsToAddBefore.push_back( finished );
-			// (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N))
-			// This pattern ensures that each unique expression is evaluated once, regardless of evaluation order of the generated C code.
-			Expression * assignFinished = UntypedExpr::createAssign( new VariableExpr(finished), new ConstantExpr( Constant::from_int( 1 ) ) );
-			ConditionalExpr * condExpr = new ConditionalExpr( new VariableExpr( finished ), var->clone(),
-				new CommaExpr( new CommaExpr( assignUnq, assignFinished ), var->clone() ) );
-			condExpr->set_result( var->get_result()->clone() );
-			condExpr->set_env( maybeClone( unqExpr->get_env() ) );
-			decls[id] = condExpr;
-		}
-		delete unqExpr;
-		return decls[id]->clone();
-	}
-
-	Expression * TupleAssignExpander::postmutate( TupleAssignExpr * assnExpr ) {
-		StmtExpr * ret = assnExpr->get_stmtExpr();
-		assnExpr->set_stmtExpr( nullptr );
-		// move env to StmtExpr
-		ret->set_env( assnExpr->get_env() );
-		assnExpr->set_env( nullptr );
-		delete assnExpr;
-		return ret;
-	}
-
-	Type * TupleTypeReplacer::postmutate( TupleType * tupleType ) {
-		unsigned tupleSize = tupleType->size();
-		if ( ! typeMap.count( tupleSize ) ) {
-			// generate struct type to replace tuple type based on the number of components in the tuple
-			StructDecl * decl = new StructDecl( toString( "_tuple", tupleSize, "_" ) );
-			decl->location = tupleType->location;
-			decl->set_body( true );
-			for ( size_t i = 0; i < tupleSize; ++i ) {
-				TypeDecl * tyParam = new TypeDecl( toString( "tuple_param_", tupleSize, "_", i ), Type::StorageClasses(), nullptr, TypeDecl::Dtype, true );
-				decl->get_members().push_back( new ObjectDecl( toString("field_", i ), Type::StorageClasses(), LinkageSpec::C, nullptr, new TypeInstType( Type::Qualifiers(), tyParam->get_name(), tyParam ), nullptr ) );
-				decl->get_parameters().push_back( tyParam );
-			}
-			if ( tupleSize == 0 ) {
-				// empty structs are not standard C. Add a dummy field to empty tuples to silence warnings when a compound literal Tuple0 is created.
-				decl->get_members().push_back( new ObjectDecl( "dummy", Type::StorageClasses(), LinkageSpec::C, nullptr, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ) );
-			}
-			typeMap[tupleSize] = decl;
-			declsToAddBefore.push_back( decl );
-		}
-		Type::Qualifiers qualifiers = tupleType->get_qualifiers();
-
-		StructDecl * decl = typeMap[tupleSize];
-		StructInstType * newType = new StructInstType( qualifiers, decl );
-		for ( auto p : group_iterate( tupleType->get_types(), decl->get_parameters() ) ) {
-			Type * t = std::get<0>(p);
-			newType->get_parameters().push_back( new TypeExpr( t->clone() ) );
-		}
-		delete tupleType;
-		return newType;
-	}
-
-	Expression * TupleIndexExpander::postmutate( TupleIndexExpr * tupleExpr ) {
-		Expression * tuple = tupleExpr->tuple;
-		assert( tuple );
-		tupleExpr->tuple = nullptr;
-		unsigned int idx = tupleExpr->index;
-		TypeSubstitution * env = tupleExpr->env;
-		tupleExpr->env = nullptr;
-		delete tupleExpr;
-
-		if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * > ( tuple ) ) {
-			if ( ! maybeImpureIgnoreUnique( tupleExpr ) ) {
-				// optimization: definitely pure tuple expr => can reduce to the only relevant component.
-				assert( tupleExpr->exprs.size() > idx );
-				Expression *& expr = *std::next(tupleExpr->exprs.begin(), idx);
-				Expression * ret = expr;
-				ret->env = env;
-				expr = nullptr; // remove from list so it can safely be deleted
-				delete tupleExpr;
-				return ret;
-			}
-		}
-
-		StructInstType * type = strict_dynamic_cast< StructInstType * >( tuple->result );
-		StructDecl * structDecl = type->baseStruct;
-		assert( structDecl->members.size() > idx );
-		Declaration * member = *std::next(structDecl->members.begin(), idx);
-		MemberExpr * memExpr = new MemberExpr( strict_dynamic_cast< DeclarationWithType * >( member ), tuple );
-		memExpr->env = env;
-		return memExpr;
-	}
-
-	Expression * replaceTupleExpr( Type * result, const std::list< Expression * > & exprs, TypeSubstitution * env ) {
-		if ( result->isVoid() ) {
-			// void result - don't need to produce a value for cascading - just output a chain of comma exprs
-			assert( ! exprs.empty() );
-			std::list< Expression * >::const_iterator iter = exprs.begin();
-			Expression * expr = new CastExpr( *iter++ );
-			for ( ; iter != exprs.end(); ++iter ) {
-				expr = new CommaExpr( expr, new CastExpr( *iter ) );
-			}
-			expr->set_env( env );
-			return expr;
-		} else {
-			// typed tuple expression - produce a compound literal which performs each of the expressions
-			// as a distinct part of its initializer - the produced compound literal may be used as part of
-			// another expression
-			std::list< Initializer * > inits;
-			for ( Expression * expr : exprs ) {
-				inits.push_back( new SingleInit( expr ) );
-			}
-			Expression * expr = new CompoundLiteralExpr( result, new ListInit( inits ) );
-			expr->set_env( env );
-			return expr;
-		}
-	}
-
-	Expression * TupleExprExpander::postmutate( TupleExpr * tupleExpr ) {
-		Type * result = tupleExpr->get_result();
-		std::list< Expression * > exprs = tupleExpr->get_exprs();
-		assert( result );
-		TypeSubstitution * env = tupleExpr->get_env();
-
-		// remove data from shell and delete it
-		tupleExpr->set_result( nullptr );
-		tupleExpr->get_exprs().clear();
-		tupleExpr->set_env( nullptr );
-		delete tupleExpr;
-
-		return replaceTupleExpr( result, exprs, env );
-	}
-
-	Type * makeTupleType( const std::list< Expression * > & exprs ) {
-		// produce the TupleType which aggregates the types of the exprs
-		std::list< Type * > types;
-		Type::Qualifiers qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic | Type::Mutex );
-		for ( Expression * expr : exprs ) {
-			assert( expr->get_result() );
-			if ( expr->get_result()->isVoid() ) {
-				// if the type of any expr is void, the type of the entire tuple is void
-				return new VoidType( Type::Qualifiers() );
-			}
-			Type * type = expr->get_result()->clone();
-			types.push_back( type );
-			// the qualifiers on the tuple type are the qualifiers that exist on all component types
-			qualifiers &= type->get_qualifiers();
-		} // for
-		if ( exprs.empty() ) qualifiers = Type::Qualifiers();
-		return new TupleType( qualifiers, types );
-	}
 	const ast::Type * makeTupleType( const std::vector<ast::ptr<ast::Expr>> & exprs ) {
 		// produce the TupleType which aggregates the types of the exprs
@@ -341,22 +52,4 @@
 	}
 
-	TypeInstType * isTtype( Type * type ) {
-		if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( type ) ) {
-			if ( inst->get_baseType() && inst->get_baseType()->get_kind() == TypeDecl::Ttype ) {
-				return inst;
-			}
-		}
-		return nullptr;
-	}
-
-	const TypeInstType * isTtype( const Type * type ) {
-		if ( const TypeInstType * inst = dynamic_cast< const TypeInstType * >( type ) ) {
-			if ( inst->baseType && inst->baseType->kind == TypeDecl::Ttype ) {
-				return inst;
-			}
-		}
-		return nullptr;
-	}
-
 	const ast::TypeInstType * isTtype( const ast::Type * type ) {
 		if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
Index: src/Tuples/Tuples.cc
===================================================================
--- src/Tuples/Tuples.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Tuples/Tuples.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -19,5 +19,4 @@
 #include "AST/Inspect.hpp"
 #include "AST/LinkageSpec.hpp"
-#include "Common/PassVisitor.h"
 #include "InitTweak/InitTweak.h"
 
@@ -25,52 +24,4 @@
 
 namespace {
-	/// Checks if impurity (read: side-effects) may exist in a piece of code.
-	/// Currently gives a very crude approximation, wherein any function
-	/// call expression means the code may be impure.
-	struct ImpurityDetector_old : public WithShortCircuiting {
-		bool const ignoreUnique;
-		bool maybeImpure;
-
-		ImpurityDetector_old( bool ignoreUnique ) :
-			ignoreUnique( ignoreUnique ), maybeImpure( false )
-		{}
-
-		void previsit( const ApplicationExpr * appExpr ) {
-			visit_children = false;
-			if ( const DeclarationWithType * function =
-					InitTweak::getFunction( appExpr ) ) {
-				if ( function->linkage == LinkageSpec::Intrinsic ) {
-					if ( function->name == "*?" || function->name == "?[?]" ) {
-						// intrinsic dereference, subscript are pure,
-						// but need to recursively look for impurity
-						visit_children = true;
-						return;
-					}
-				}
-			}
-			maybeImpure = true;
-		}
-
-		void previsit( const UntypedExpr * ) {
-			maybeImpure = true;
-			visit_children = false;
-		}
-
-		void previsit( const UniqueExpr * ) {
-			if ( ignoreUnique ) {
-				// bottom out at unique expression.
-				// The existence of a unique expression doesn't change the purity of an expression.
-				// That is, even if the wrapped expression is impure, the wrapper protects the rest of the expression.
-				visit_children = false;
-				return;
-			}
-		}
-	};
-
-	bool detectImpurity( const Expression * expr, bool ignoreUnique ) {
-		PassVisitor<ImpurityDetector_old> detector( ignoreUnique );
-		expr->accept( detector );
-		return detector.pass.maybeImpure;
-	}
 
 	/// Determines if impurity (read: side-effects) may exist in a piece of code. Currently gives
@@ -110,12 +61,4 @@
 }
 
-bool maybeImpure( const Expression * expr ) {
-	return detectImpurity( expr, false );
-}
-
-bool maybeImpureIgnoreUnique( const Expression * expr ) {
-	return detectImpurity( expr, true );
-}
-
 } // namespace Tuples
 
Index: src/Tuples/Tuples.h
===================================================================
--- src/Tuples/Tuples.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Tuples/Tuples.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -21,15 +21,8 @@
 #include "AST/Fwd.hpp"
 #include "AST/Node.hpp"
-#include "SynTree/Expression.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/Type.h"
-
-#include "ResolvExpr/AlternativeFinder.h"
 #include "ResolvExpr/CandidateFinder.hpp"
 
 namespace Tuples {
 	// TupleAssignment.cc
-	void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign,
-		std::vector< ResolvExpr::AlternativeFinder >& args );
 	void handleTupleAssignment(
 		ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
@@ -38,31 +31,23 @@
 	// TupleExpansion.cc
 	/// expands z.[a, b.[x, y], c] into [z.a, z.b.x, z.b.y, z.c], inserting UniqueExprs as appropriate
-	void expandMemberTuples( std::list< Declaration * > & translationUnit );
 	void expandMemberTuples( ast::TranslationUnit & translationUnit );
 
 	/// replaces tuple-related elements, such as TupleType, TupleExpr, TupleAssignExpr, etc.
-	void expandTuples( std::list< Declaration * > & translationUnit );
 	void expandTuples( ast::TranslationUnit & translaionUnit );
 
 	/// replaces UniqueExprs with a temporary variable and one call
-	void expandUniqueExpr( std::list< Declaration * > & translationUnit );
 	void expandUniqueExpr( ast::TranslationUnit & translationUnit );
 
 	/// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types
-	Type * makeTupleType( const std::list< Expression * > & exprs );
 	const ast::Type * makeTupleType( const std::vector<ast::ptr<ast::Expr>> & exprs );
 
 	/// returns a TypeInstType if `type` is a ttype, nullptr otherwise
-	TypeInstType * isTtype( Type * type );
-	const TypeInstType * isTtype( const Type * type );
 	const ast::TypeInstType * isTtype( const ast::Type * type );
 
 	/// returns true if the expression may contain side-effects.
-	bool maybeImpure( const Expression * expr );
 	bool maybeImpure( const ast::Expr * expr );
 
 	/// Returns true if the expression may contain side-effect,
 	/// ignoring the presence of unique expressions.
-	bool maybeImpureIgnoreUnique( const Expression * expr );
 	bool maybeImpureIgnoreUnique( const ast::Expr * expr );
 } // namespace Tuples
Index: src/Validate/Autogen.cpp
===================================================================
--- src/Validate/Autogen.cpp	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Validate/Autogen.cpp	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -49,5 +49,5 @@
 
 // --------------------------------------------------------------------------
-struct AutogenerateRoutines_new final :
+struct AutogenerateRoutines final :
 		public ast::WithDeclsToAdd<>,
 		public ast::WithShortCircuiting {
@@ -232,5 +232,5 @@
 
 // --------------------------------------------------------------------------
-void AutogenerateRoutines_new::previsit( const ast::EnumDecl * enumDecl ) {
+void AutogenerateRoutines::previsit( const ast::EnumDecl * enumDecl ) {
 	// Must visit children (enum constants) to add them to the symbol table.
 	if ( !enumDecl->body ) return;
@@ -249,5 +249,5 @@
 }
 
-void AutogenerateRoutines_new::previsit( const ast::StructDecl * structDecl ) {
+void AutogenerateRoutines::previsit( const ast::StructDecl * structDecl ) {
 	visit_children = false;
 	if ( !structDecl->body ) return;
@@ -265,5 +265,5 @@
 }
 
-void AutogenerateRoutines_new::previsit( const ast::UnionDecl * unionDecl ) {
+void AutogenerateRoutines::previsit( const ast::UnionDecl * unionDecl ) {
 	visit_children = false;
 	if ( !unionDecl->body ) return;
@@ -282,5 +282,5 @@
 
 /// Generate ctor/dtors/assign for typedecls, e.g., otype T = int *;
-void AutogenerateRoutines_new::previsit( const ast::TypeDecl * typeDecl ) {
+void AutogenerateRoutines::previsit( const ast::TypeDecl * typeDecl ) {
 	if ( !typeDecl->base ) return;
 
@@ -290,10 +290,10 @@
 }
 
-void AutogenerateRoutines_new::previsit( const ast::TraitDecl * ) {
+void AutogenerateRoutines::previsit( const ast::TraitDecl * ) {
 	// Ensure that we don't add assignment ops for types defined as part of the trait
 	visit_children = false;
 }
 
-void AutogenerateRoutines_new::previsit( const ast::FunctionDecl * ) {
+void AutogenerateRoutines::previsit( const ast::FunctionDecl * ) {
 	// Track whether we're currently in a function.
 	// Can ignore function type idiosyncrasies, because function type can never
@@ -302,5 +302,5 @@
 }
 
-void AutogenerateRoutines_new::postvisit( const ast::FunctionDecl * ) {
+void AutogenerateRoutines::postvisit( const ast::FunctionDecl * ) {
 	functionNesting -= 1;
 }
@@ -521,5 +521,5 @@
 		const ast::Expr * src, const ast::ObjectDecl * field,
 		ast::FunctionDecl * func, SymTab::LoopDirection direction ) {
-	InitTweak::InitExpander_new srcParam( src );
+	InitTweak::InitExpander srcParam( src );
 	// Assign to destination.
 	ast::MemberExpr * dstSelect = new ast::MemberExpr(
@@ -795,5 +795,5 @@
 
 void autogenerateRoutines( ast::TranslationUnit & translationUnit ) {
-	ast::Pass<AutogenerateRoutines_new>::run( translationUnit );
+	ast::Pass<AutogenerateRoutines>::run( translationUnit );
 }
 
Index: c/Validate/FindSpecialDecls.cc
===================================================================
--- src/Validate/FindSpecialDecls.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,100 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// FindSpecialDecls.cc --
-//
-// Author           : Rob Schluntz
-// Created On       : Thu Aug 30 09:49:43 2018
-// Last Modified By : Rob Schluntz
-// Last Modified On : Thu Aug 30 09:55:25 2018
-// Update Count     : 2
-//
-
-#include "FindSpecialDecls.h"
-
-#include "Common/PassVisitor.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/Type.h"
-
-// NOTE: currently, it is assumed that every special declaration occurs at the top-level,
-// so function bodies, aggregate bodies, object initializers, etc. are not visited.
-// If this assumption changes, e.g., with the introduction of namespaces, remove the visit_children assignments.
-
-namespace Validate {
-	Type * SizeType = nullptr;
-	FunctionDecl * dereferenceOperator = nullptr;
-	StructDecl * dtorStruct = nullptr;
-	FunctionDecl * dtorStructDestroy = nullptr;
-
-	namespace {
-		struct FindSpecialDecls final : public WithShortCircuiting {
-			void previsit( ObjectDecl * objDecl );
-			void previsit( FunctionDecl * funcDecl );
-			void previsit( StructDecl * structDecl );
-			void previsit( UnionDecl * unionDecl );
-			void previsit( EnumDecl * enumDecl );
-			void previsit( TraitDecl * traitDecl );
-		};
-	} // namespace
-
-	void findSpecialDecls( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<FindSpecialDecls> finder;
-		acceptAll( translationUnit, finder );
-		// TODO: conditionally generate 'fake' declarations for missing features, so that
-		// translation can proceed in the event that builtins, prelude, etc. are missing.
-	}
-
-	namespace {
-		void FindSpecialDecls::previsit( ObjectDecl * ) {
-			visit_children = false;
-		}
-
-		void FindSpecialDecls::previsit( FunctionDecl * funcDecl ) {
-			visit_children = false;
-			if ( ! dereferenceOperator && funcDecl->name == "*?" && funcDecl->linkage == LinkageSpec::Intrinsic ) {
-				// find and remember the intrinsic dereference operator for object pointers
-				FunctionType * ftype = funcDecl->type;
-				if ( ftype->parameters.size() == 1 ) {
-					PointerType * ptrType = strict_dynamic_cast<PointerType *>( ftype->parameters.front()->get_type() );
-					if ( ptrType->base->get_qualifiers() == Type::Qualifiers() ) {
-						TypeInstType * inst = dynamic_cast<TypeInstType *>( ptrType->base );
-						if ( inst && ! inst->get_isFtype() ) {
-							dereferenceOperator = funcDecl;
-						}
-					}
-				}
-			} else if ( ! dtorStructDestroy && funcDecl->name == "__destroy_Destructor" ) {
-				dtorStructDestroy = funcDecl;
-			}
-		}
-
-		void FindSpecialDecls::previsit( StructDecl * structDecl ) {
-			visit_children = false;
-			if ( ! dtorStruct && structDecl->name == "__Destructor" ) {
-				dtorStruct = structDecl;
-			}
-		}
-
-		void FindSpecialDecls::previsit( UnionDecl * ) {
-			visit_children = false;
-		}
-
-		void FindSpecialDecls::previsit( EnumDecl * ) {
-			visit_children = false;
-		}
-
-		void FindSpecialDecls::previsit( TraitDecl * ) {
-			visit_children = false;
-		}
-
-	} // namespace
-} // namespace Validate
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/Validate/FindSpecialDecls.h
===================================================================
--- src/Validate/FindSpecialDecls.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Validate/FindSpecialDecls.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,11 +16,4 @@
 #pragma once
 
-#include <list>  // for list
-
-class Declaration;
-class FunctionDecl;
-class StructDecl;
-class Type;
-
 namespace ast {
 	class TranslationUnit;
@@ -28,18 +21,4 @@
 
 namespace Validate {
-	/// size_t type - set when size_t typedef is seen. Useful in a few places,
-	/// such as in determining array dimension type
-	extern Type * SizeType;
-
-	/// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations.
-	/// Useful for creating dereference ApplicationExprs without a full resolver pass.
-	extern FunctionDecl * dereferenceOperator;
-
-	/// special built-in functions and data structures necessary for destructor generation
-	extern StructDecl * dtorStruct;
-	extern FunctionDecl * dtorStructDestroy;
-
-	/// find and remember some of the special declarations that are useful for generating code, so that they do not have to be discovered multiple times.
-	void findSpecialDecls( std::list< Declaration * > & translationUnit );
 
 /// Find and remember some of the special declarations that are useful for
Index: c/Validate/HandleAttributes.cc
===================================================================
--- src/Validate/HandleAttributes.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,87 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// HandleAttributes.cc --
-//
-// Author           : Rob Schluntz
-// Created On       : Fri Jul 27 10:15:06 2018
-// Last Modified By : Rob Schluntz
-// Last Modified On : Fri Jul 27 10:16:43 2018
-// Update Count     : 2
-//
-
-#include "HandleAttributes.h"
-
-#include "CompilationState.h"
-#include "Common/Eval.h"
-#include "Common/PassVisitor.h"
-#include "Common/ToString.hpp"
-#include "Common/SemanticError.h"
-#include "ResolvExpr/Resolver.h"
-#include "SynTree/Attribute.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/Type.h"
-
-namespace Validate {
-	namespace {
-		struct HandleAttributes : public WithIndexer {
-			void previsit( ObjectDecl * decl );
-			void previsit( FunctionDecl * decl );
-		};
-	} // namespace
-
-	void handleAttributes( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<HandleAttributes> handler;
-		acceptAll( translationUnit, handler );
-	}
-
-	namespace {
-		void HandleAttributes::previsit( ObjectDecl * decl ) {
-			for ( Attribute * attr : decl->attributes ) {
-				std::string name = attr->normalizedName();
-				if (name == "init_priority") {
-					// TODO: implement C++-like init_priority attribute
-				}
-			}
-		}
-
-		void HandleAttributes::previsit( FunctionDecl * decl ) {
-			for ( Attribute * attr : decl->attributes ) {
-				std::string name = attr->normalizedName();
-				if (name == "constructor" || name == "destructor") {
-					if (attr->parameters.size() == 1) {
-						Expression *& arg = attr->parameters.front();
-						ResolvExpr::findSingleExpression( arg, new BasicType( Type::Qualifiers(), BasicType::LongLongSignedInt ), indexer );
-						auto result = eval(arg);
-						if (! result.second) {
-							SemanticWarning(attr->location, Warning::GccAttributes,
-								toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
-							return;
-						}
-						auto priority = result.first;
-						if (priority < 101) {
-							SemanticWarning(attr->location, Warning::GccAttributes,
-								toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) );
-						} else if (priority < 201 && ! buildingLibrary()) {
-							SemanticWarning(attr->location, Warning::GccAttributes,
-								toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) );
-						}
-					} else if (attr->parameters.size() > 1) {
-						SemanticWarning(attr->location, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) );
-					} else {
-						SemanticWarning(attr->location, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) );
-					}
-				}
-			}
-		}
-	} // namespace
-} // namespace Validate
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/Validate/HandleAttributes.h
===================================================================
--- src/Validate/HandleAttributes.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ 	(revision )
@@ -1,30 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// HandleAttributes.h --
-//
-// Author           : Rob Schluntz
-// Created On       : Fri Jul 27 10:10:10 2018
-// Last Modified By : Rob Schluntz
-// Last Modified On : Fri Jul 27 10:12:53 2018
-// Update Count     : 2
-//
-
-#pragma once
-
-#include <list>  // for list
-
-class Declaration;
-
-namespace Validate {
-	void handleAttributes( std::list< Declaration * > &translationUnit );
-} // namespace Validate
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/Validate/module.mk
===================================================================
--- src/Validate/module.mk	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Validate/module.mk	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -16,5 +16,4 @@
 
 SRC_VALIDATE = \
-	Validate/FindSpecialDecls.cc \
 	Validate/FindSpecialDecls.h
 
@@ -37,6 +36,4 @@
 	Validate/GenericParameter.cpp \
 	Validate/GenericParameter.hpp \
-	Validate/HandleAttributes.cc \
-	Validate/HandleAttributes.h \
 	Validate/HoistStruct.cpp \
 	Validate/HoistStruct.hpp \
Index: src/Virtual/ExpandCasts.cc
===================================================================
--- src/Virtual/ExpandCasts.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Virtual/ExpandCasts.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -24,13 +24,7 @@
 #include "AST/Expr.hpp"
 #include "AST/Pass.hpp"
-#include "Common/PassVisitor.h"    // for PassVisitor
 #include "Common/ScopedMap.h"      // for ScopedMap
 #include "Common/SemanticError.h"  // for SemanticError
 #include "SymTab/Mangler.h"        // for mangleType
-#include "SynTree/Declaration.h"   // for ObjectDecl, StructDecl, FunctionDecl
-#include "SynTree/Expression.h"    // for VirtualCastExpr, CastExpr, Address...
-#include "SynTree/Mutator.h"       // for mutateAll
-#include "SynTree/Type.h"          // for Type, PointerType, StructInstType
-#include "SynTree/Visitor.h"       // for acceptAll
 
 namespace Virtual {
@@ -43,9 +37,4 @@
 }
 
-bool is_type_id_object( const ObjectDecl * objectDecl ) {
-	const std::string & objectName = objectDecl->name;
-	return is_prefix( "__cfatid_", objectName );
-}
-
 bool is_type_id_object( const ast::ObjectDecl * decl ) {
 	return is_prefix( "__cfatid_", decl->name );
@@ -55,219 +44,4 @@
 
 	/// Maps virtual table types the instance for that type.
-	class VirtualTableMap final {
-		ScopedMap<std::string, ObjectDecl *> vtable_instances;
-	public:
-		void enterScope() {
-			vtable_instances.beginScope();
-		}
-		void leaveScope() {
-			vtable_instances.endScope();
-		}
-
-		ObjectDecl * insert( ObjectDecl * vtableDecl ) {
-			std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type );
-			ObjectDecl *& value = vtable_instances[ mangledName ];
-			if ( value ) {
-				if ( vtableDecl->storageClasses.is_extern ) {
-					return nullptr;
-				} else if ( ! value->storageClasses.is_extern ) {
-					return value;
-				}
-			}
-			value = vtableDecl;
-			return nullptr;
-		}
-
-		ObjectDecl * lookup( const Type * vtableType ) {
-			std::string const & mangledName = SymTab::Mangler::mangleType( vtableType );
-			const auto it = vtable_instances.find( mangledName );
-			return ( vtable_instances.end() == it ) ? nullptr : it->second;
-		}
-	};
-
-	class VirtualCastCore {
-		CastExpr * cast_to_type_id( Expression * expr, int level_of_indirection ) {
-			Type * type = new StructInstType(
-				Type::Qualifiers( Type::Const ), pvt_decl );
-			for (int i = 0 ; i < level_of_indirection ; ++i) {
-				type = new PointerType( noQualifiers, type );
-			}
-			return new CastExpr( expr, type );
-		}
-
-	public:
-		VirtualCastCore() :
-			indexer(), vcast_decl( nullptr ), pvt_decl( nullptr )
-		{}
-
-		void premutate( FunctionDecl * functionDecl );
-		void premutate( StructDecl * structDecl );
-		void premutate( ObjectDecl * objectDecl );
-
-		Expression * postmutate( VirtualCastExpr * castExpr );
-
-		VirtualTableMap indexer;
-	private:
-		FunctionDecl *vcast_decl;
-		StructDecl *pvt_decl;
-	};
-
-	void VirtualCastCore::premutate( FunctionDecl * functionDecl ) {
-		if ( (! vcast_decl) &&
-		     functionDecl->get_name() == "__cfavir_virtual_cast" ) {
-			vcast_decl = functionDecl;
-		}
-	}
-
-	void VirtualCastCore::premutate( StructDecl * structDecl ) {
-		if ( pvt_decl || ! structDecl->has_body() ) {
-			return;
-		} else if ( structDecl->get_name() == "__cfavir_type_info" ) {
-			pvt_decl = structDecl;
-		}
-	}
-
-	void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
-		if ( is_type_id_object( objectDecl ) ) {
-			// Multiple definitions should be fine because of linkonce.
-			indexer.insert( objectDecl );
-		}
-	}
-
-	/// Better error locations for generated casts.
-	CodeLocation castLocation( const VirtualCastExpr * castExpr ) {
-		if ( castExpr->location.isSet() ) {
-			return castExpr->location;
-		} else if ( castExpr->arg->location.isSet() ) {
-			return castExpr->arg->location;
-		} else if ( castExpr->result->location.isSet() ) {
-			return castExpr->result->location;
-		} else {
-			return CodeLocation();
-		}
-	}
-
-	[[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) {
-		SemanticError( castLocation( castExpr ), message );
-	}
-
-	/// Get the base type from a pointer or reference.
-	const Type * getBaseType( const Type * type ) {
-		if ( auto target = dynamic_cast<const PointerType *>( type ) ) {
-			return target->base;
-		} else if ( auto target = dynamic_cast<const ReferenceType *>( type ) ) {
-			return target->base;
-		} else {
-			return nullptr;
-		}
-	}
-
-	/* Attempt to follow the "head" field of the structure to get the...
-	 * Returns nullptr on error, otherwise owner must free returned node.
-	 */
-	StructInstType * followHeadPointerType(
-			const StructInstType * oldType,
-			const std::string& fieldName,
-			const CodeLocation& errorLocation ) {
-
-		// First section of the function is all about trying to fill this variable in.
-		StructInstType * newType = nullptr;
-		{
-			const StructDecl * oldDecl = oldType->baseStruct;
-			assert( oldDecl );
-
-			// Helper function for throwing semantic errors.
-			auto throwError = [&fieldName, &errorLocation, &oldDecl](const std::string& message) {
-				const std::string& context = "While following head pointer of " +
-					oldDecl->name + " named '" + fieldName + "': ";
-				SemanticError( errorLocation, context + message );
-			};
-
-			if ( oldDecl->members.empty() ) {
-				throwError( "Type has no fields." );
-			}
-			const Declaration * memberDecl = oldDecl->members.front();
-			assert( memberDecl );
-			const ObjectDecl * fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
-			assert( fieldDecl );
-			if ( fieldName != fieldDecl->name ) {
-				throwError( "Head field did not have expected name." );
-			}
-
-			const Type * fieldType = fieldDecl->type;
-			if ( nullptr == fieldType ) {
-				throwError( "Could not get head field." );
-			}
-			const PointerType * ptrType = dynamic_cast<const PointerType *>( fieldType );
-			if ( nullptr == ptrType ) {
-				throwError( "First field is not a pointer type." );
-			}
-			assert( ptrType->base );
-			newType = dynamic_cast<StructInstType *>( ptrType->base );
-			if ( nullptr == newType ) {
-				throwError( "First field does not point to a structure type." );
-			}
-		}
-
-		// Now we can look into copying it.
-		newType = newType->clone();
-		if ( ! oldType->parameters.empty() ) {
-			deleteAll( newType->parameters );
-			newType->parameters.clear();
-			cloneAll( oldType->parameters, newType->parameters );
-		}
-		return newType;
-	}
-
-	/// Get the type-id type from a virtual type.
-	StructInstType * getTypeIdType( const Type * type, const CodeLocation& errorLocation ) {
-		const StructInstType * typeInst = dynamic_cast<const StructInstType *>( type );
-		if ( nullptr == typeInst ) {
-			return nullptr;
-		}
-		StructInstType * tableInst =
-			followHeadPointerType( typeInst, "virtual_table", errorLocation );
-		if ( nullptr == tableInst ) {
-			return nullptr;
-		}
-		StructInstType * typeIdInst =
-			followHeadPointerType( tableInst, "__cfavir_typeid", errorLocation );
-		delete tableInst;
-		return typeIdInst;
-	}
-
-	Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
-		assertf( castExpr->result, "Virtual Cast target not found before expansion." );
-
-		assert( vcast_decl );
-		assert( pvt_decl );
-
-		const Type * base_type = getBaseType( castExpr->result );
-		if ( nullptr == base_type ) {
-			castError( castExpr, "Virtual cast target must be a pointer or reference type." );
-		}
-		const Type * type_id_type = getTypeIdType( base_type, castLocation( castExpr ) );
-		if ( nullptr == type_id_type ) {
-			castError( castExpr, "Ill formed virtual cast target type." );
-		}
-		ObjectDecl * type_id = indexer.lookup( type_id_type );
-		delete type_id_type;
-		if ( nullptr == type_id ) {
-			castError( castExpr, "Virtual cast does not target a virtual type." );
-		}
-
-		Expression * result = new CastExpr(
-			new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
-				cast_to_type_id( new AddressExpr( new VariableExpr( type_id ) ), 1 ),
-				cast_to_type_id( castExpr->get_arg(), 2 ),
-			} ),
-			castExpr->get_result()->clone()
-		);
-
-		castExpr->set_arg( nullptr );
-		castExpr->set_result( nullptr );
-		delete castExpr;
-		return result;
-	}
 
 /// Better error locations for generated casts.
@@ -494,9 +268,4 @@
 } // namespace
 
-void expandCasts( std::list< Declaration * > & translationUnit ) {
-	PassVisitor<VirtualCastCore> translator;
-	mutateAll( translationUnit, translator );
-}
-
 void expandCasts( ast::TranslationUnit & translationUnit ) {
 	ast::Pass<ExpandCastsCore>::run( translationUnit );
Index: src/Virtual/Tables.cc
===================================================================
--- src/Virtual/Tables.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Virtual/Tables.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -21,9 +21,4 @@
 #include "AST/Stmt.hpp"
 #include "AST/Type.hpp"
-#include <SynTree/Attribute.h>
-#include <SynTree/Declaration.h>
-#include <SynTree/Expression.h>
-#include <SynTree/Statement.h>
-#include <SynTree/Type.h>
 
 namespace Virtual {
@@ -65,21 +60,4 @@
 	return 17 < name.size() && '_' == name[0] &&
 		std::string("_vtable_instance") == name.substr(1, name.size() - 17);
-}
-
-static ObjectDecl * makeVtableDeclaration(
-		std::string const & name,
-		StructInstType * type, Initializer * init ) {
-	Type::StorageClasses storage = noStorageClasses;
-	if ( nullptr == init ) {
-		storage.is_extern = true;
-	}
-	return new ObjectDecl(
-		name,
-		storage,
-		LinkageSpec::Cforall,
-		nullptr,
-		type,
-		init
-	);
 }
 
@@ -101,9 +79,4 @@
 }
 
-ObjectDecl * makeVtableForward( std::string const & name, StructInstType * type ) {
-	assert( type );
-	return makeVtableDeclaration( name, type, nullptr );
-}
-
 ast::ObjectDecl * makeVtableForward(
 		CodeLocation const & location, std::string const & name,
@@ -111,45 +84,4 @@
 	assert( vtableType );
 	return makeVtableDeclaration( location, name, vtableType, nullptr );
-}
-
-ObjectDecl * makeVtableInstance(
-		std::string const & name, StructInstType * vtableType,
-		Type * objectType, Initializer * init ) {
-	assert( vtableType );
-	assert( objectType );
-	StructDecl * vtableStruct = vtableType->baseStruct;
-	// Build the initialization
-	if ( nullptr == init ) {
-		std::list< Initializer * > inits;
-
-		// This is going to have to be run before the resolver to connect expressions.
-		for ( auto field : vtableStruct->members ) {
-			if ( std::string( "parent" ) == field->name ) {
-				// This will not work with polymorphic state.
-				auto oField = strict_dynamic_cast< ObjectDecl * >( field );
-				auto fieldType = strict_dynamic_cast< PointerType * >( oField->type );
-				auto parentType = strict_dynamic_cast< StructInstType * >( fieldType->base );
-				std::string const & parentInstance = instanceName( parentType->name );
-				inits.push_back(
-						new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
-			} else if ( std::string( "__cfavir_typeid" ) == field->name ) {
-				std::string const & baseType = baseTypeName( vtableType->name );
-				std::string const & typeId = typeIdName( baseType );
-				inits.push_back( new SingleInit( new AddressExpr( new NameExpr( typeId ) ) ) );
-			} else if ( std::string( "size" ) == field->name ) {
-				inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
-			} else if ( std::string( "align" ) == field->name ) {
-				inits.push_back( new SingleInit( new AlignofExpr( objectType->clone() ) ) );
-			} else {
-				inits.push_back( new SingleInit( new NameExpr( field->name ) ) );
-			}
-		}
-		init = new ListInit( inits );
-	// This should initialize everything except the parent pointer, the
-	// size-of and align-of fields. These should be inserted.
-	} else {
-		assert(false);
-	}
-	return makeVtableDeclaration( name, vtableType, init );
 }
 
@@ -224,37 +156,4 @@
 }
 
-FunctionDecl * makeGetExceptionForward(
-		Type * vtableType, Type * exceptType ) {
-	assert( vtableType );
-	assert( exceptType );
-	FunctionType * type = new FunctionType( noQualifiers, false );
-	vtableType->tq.is_const = true;
-	type->returnVals.push_back( new ObjectDecl(
-		"_retvalue",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new ReferenceType( noQualifiers, vtableType ),
-		nullptr,
-		{ new Attribute("unused") }
-	) );
-	type->parameters.push_back( new ObjectDecl(
-		"__unused",
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		nullptr,
-		new PointerType( noQualifiers, exceptType ),
-		nullptr,
-		{ new Attribute("unused") }
-	) );
-	return new FunctionDecl(
-		functionName,
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		type,
-		nullptr
-	);
-}
-
 ast::FunctionDecl * makeGetExceptionForward(
 		CodeLocation const & location,
@@ -284,16 +183,4 @@
 }
 
-FunctionDecl * makeGetExceptionFunction(
-		ObjectDecl * vtableInstance, Type * exceptType ) {
-	assert( vtableInstance );
-	assert( exceptType );
-	FunctionDecl * func = makeGetExceptionForward(
-		vtableInstance->type->clone(), exceptType );
-	func->statements = new CompoundStmt( {
-		new ReturnStmt( new VariableExpr( vtableInstance ) ),
-	} );
-	return func;
-}
-
 ast::FunctionDecl * makeGetExceptionFunction(
 		CodeLocation const & location,
@@ -307,23 +194,4 @@
 	} );
 	return func;
-}
-
-ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) {
-	assert( typeIdType );
-	StructInstType * type = typeIdType->clone();
-	type->tq.is_const = true;
-	std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
-	return new ObjectDecl(
-		typeid_name,
-		noStorageClasses,
-		LinkageSpec::Cforall,
-		/* bitfieldWidth */ nullptr,
-		type,
-		new ListInit( { new SingleInit(
-			new AddressExpr( new NameExpr( "__cfatid_exception_t" ) )
-			) } ),
-		{ new Attribute( "cfa_linkonce", {} ) },
-		noFuncSpecifiers
-	);
 }
 
Index: src/Virtual/Tables.h
===================================================================
--- src/Virtual/Tables.h	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/Virtual/Tables.h	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -18,12 +18,4 @@
 #include <string>
 #include "AST/Fwd.hpp"
-class Declaration;
-class Expression;
-class FunctionDecl;
-class Initializer;
-class ObjectDecl;
-class StructDecl;
-class StructInstType;
-class Type;
 
 namespace Virtual {
@@ -37,6 +29,4 @@
 bool isVTableInstanceName( std::string const & name );
 
-ObjectDecl * makeVtableForward(
-	std::string const & name, StructInstType * vtableType );
 /* Create a forward declaration of a vtable of the given type.
  * vtableType node is consumed.
@@ -46,8 +36,4 @@
 	ast::StructInstType const * vtableType );
 
-ObjectDecl * makeVtableInstance(
-	std::string const & name,
-	StructInstType * vtableType, Type * objectType,
-	Initializer * init = nullptr );
 /* Create an initialized definition of a vtable.
  * vtableType and init (if provided) nodes are consumed.
@@ -61,5 +47,5 @@
 
 // Some special code for how exceptions interact with virtual tables.
-FunctionDecl * makeGetExceptionForward( Type * vtableType, Type * exceptType );
+
 /* Create a forward declaration of the exception virtual function
  * linking the vtableType to the exceptType. Both nodes are consumed.
@@ -70,6 +56,4 @@
 	ast::Type const * exceptType );
 
-FunctionDecl * makeGetExceptionFunction(
-	ObjectDecl * vtableInstance, Type * exceptType );
 /* Create the definition of the exception virtual function.
  * exceptType node is consumed.
@@ -79,5 +63,4 @@
 	ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType );
 
-ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType );
 /* Build an instance of the type-id from the type of the type-id.
  * TODO: Should take the parent type. Currently locked to the exception_t.
Index: src/main.cc
===================================================================
--- src/main.cc	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ src/main.cc	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -29,5 +29,4 @@
 #include <string>                           // for char_traits, operator<<
 
-#include "AST/Convert.hpp"
 #include "AST/Pass.hpp"                     // for pass_visitor_stats
 #include "AST/Print.hpp"                    // for printAll
@@ -40,5 +39,4 @@
 #include "CodeGen/Generate.h"               // for generate
 #include "CodeGen/LinkOnce.h"               // for translateLinkOnce
-#include "CodeTools/TrackLoc.h"             // for fillLocations
 #include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
 #include "Common/DeclStats.hpp"             // for printDeclStats
@@ -66,6 +64,4 @@
 #include "ResolvExpr/EraseWith.hpp"         // for eraseWith
 #include "ResolvExpr/Resolver.h"            // for resolve
-#include "SynTree/LinkageSpec.h"            // for Spec, Cforall, Intrinsic
-#include "SynTree/Declaration.h"            // for Declaration
 #include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
 #include "Validate/Autogen.hpp"             // for autogenerateRoutines
@@ -101,9 +97,4 @@
 		ast::pass_visitor_stats.max = build<MaxCounter<double>>( "Max Depth", pass );
 	}
-	{
-		static auto group = build<CounterGroup>( "Syntax Node" );
-		auto pass = build<CounterGroup>( name, group );
-		BaseSyntaxNode::new_nodes = build<SimpleCounter>( "Allocs", pass );
-	}
 }
 
@@ -259,5 +250,4 @@
 
 	parse_cmdline( argc, argv );						// process command-line arguments
-	CodeGen::FixMain::setReplaceMain( !nomainp );
 
 	if ( waiting_for_gdb ) {
@@ -403,4 +393,5 @@
 		PASS( "Translate Tries", ControlStruct::translateTries, transUnit );
 		PASS( "Gen Waitfor", Concurrency::generateWaitFor, transUnit );
+		PASS( "Fix Main Linkage", CodeGen::fixMainLinkage, transUnit, !nomainp );
 
 		// Needs to happen before tuple types are expanded.
@@ -430,6 +421,6 @@
 
 		PASS( "Code Gen", CodeGen::generate, transUnit, *output, !genproto, prettycodegenp, true, linemarks, false );
-
-		CodeGen::FixMain::fix( transUnit, *output, (PreludeDirector + "/bootloader.c").c_str() );
+		CodeGen::fixMainInvoke( transUnit, *output, (PreludeDirector + "/bootloader.c").c_str() );
+
 		if ( output != &cout ) {
 			delete output;
Index: tests/concurrency/waitfor/parse.cfa
===================================================================
--- tests/concurrency/waitfor/parse.cfa	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ tests/concurrency/waitfor/parse.cfa	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -10,6 +10,6 @@
 // Created On       : Wed Aug 30 17:53:29 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Apr 10 22:52:18 2023
-// Update Count     : 64
+// Last Modified On : Wed Nov  1 07:28:19 2023
+// Update Count     : 65
 // 
 
@@ -258,4 +258,4 @@
 // Local Variables: //
 // tab-width: 4 //
-// compile-command: "cfa waitfor.cfa" //
+// compile-command: "cfa parse.cfa" //
 // End: //
Index: tests/io/.expect/manipulatorsInput.arm64.txt
===================================================================
--- tests/io/.expect/manipulatorsInput.arm64.txt	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ tests/io/.expect/manipulatorsInput.arm64.txt	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -24,15 +24,15 @@
 3 abcxxx
 4 aaaaaaaa
-5 aaaaaaaa
+5
 6 aabbccbb
 7 dddwww
-8 dddwww
-9 dddwww
+8
+9
 10 aaaaaaaa
 11 wwwwwwww
-12 wwwwwwww
-13 wwwwwwww
+12
+13
 14 cccc
-15 q
+15
 a
 a
Index: tests/io/.expect/manipulatorsInput.x64.txt
===================================================================
--- tests/io/.expect/manipulatorsInput.x64.txt	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ tests/io/.expect/manipulatorsInput.x64.txt	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -24,15 +24,15 @@
 3 abcxxx
 4 aaaaaaaa
-5 aaaaaaaa
+5
 6 aabbccbb
 7 dddwww
-8 dddwww
-9 dddwww
+8
+9
 10 aaaaaaaa
 11 wwwwwwww
-12 wwwwwwww
-13 wwwwwwww
+12
+13
 14 cccc
-15 q
+15
 a
 a
Index: tests/io/.expect/manipulatorsInput.x86.txt
===================================================================
--- tests/io/.expect/manipulatorsInput.x86.txt	(revision df8ba61a560c37035667d49f8da03d295dd8b96e)
+++ tests/io/.expect/manipulatorsInput.x86.txt	(revision 8d182b1ed853a31c8c46021c2f2a6be9c45ea31d)
@@ -24,15 +24,15 @@
 3 abcxxx
 4 aaaaaaaa
-5 aaaaaaaa
+5
 6 aabbccbb
 7 dddwww
-8 dddwww
-9 dddwww
+8
+9
 10 aaaaaaaa
 11 wwwwwwww
-12 wwwwwwww
-13 wwwwwwww
+12
+13
 14 cccc
-15 q
+15
 a
 a
