Index: doc/theses/fangren_yu_COOP_S20/Makefile
===================================================================
--- doc/theses/fangren_yu_COOP_S20/Makefile	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
+++ doc/theses/fangren_yu_COOP_S20/Makefile	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -0,0 +1,89 @@
+## Define the configuration variables.
+
+Build = build
+Figures = figures
+Macros = ../../LaTeXmacros
+TeXLIB = .:${Macros}:${Build}:
+LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
+BibTeX = BIBINPUTS=../../bibliography: && export BIBINPUTS && bibtex
+
+MAKEFLAGS = --no-print-directory --silent #
+VPATH = ${Build} ${Figures}
+
+## Define the text source files.
+
+SOURCES = ${addsuffix .tex, \
+Report \
+}
+
+FIGURES = ${addsuffix .tex, \
+DeepNodeSharing \
+}
+
+PICTURES = ${addsuffix .pstex, \
+}
+
+PROGRAMS = ${addsuffix .tex, \
+}
+
+GRAPHS = ${addsuffix .tex, \
+}
+
+## Define the documents that need to be made.
+
+DOCUMENT = Report.pdf
+BASE = ${basename ${DOCUMENT}}
+
+# Directives #
+
+.PHONY : all clean					# not file names
+
+all : ${DOCUMENT}
+
+clean :
+	@rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
+
+# File Dependencies #
+
+
+${DOCUMENT} : ${BASE}.ps
+	ps2pdf $<
+
+${BASE}.ps : ${BASE}.dvi
+	dvips ${Build}/$< -o $@
+
+${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
+		${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../../bibliography/pl.bib | ${Build}
+	# Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
+	if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
+	# Must have *.aux file containing citations for bibtex
+	if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
+	-${BibTeX} ${Build}/${basename $@}
+	# Some citations reference others so run again to resolve these citations
+	${LaTeX} ${basename $@}.tex
+	-${BibTeX} ${Build}/${basename $@}
+	# Make index from *.aux entries and input index at end of document
+	makeindex -s ${Macros}/indexstyle ${Build}/${basename $@}.idx
+	# Run again to finish citations
+	${LaTeX} ${basename $@}.tex
+	# Run again to get index title into table of contents
+	${LaTeX} ${basename $@}.tex
+
+## Define the default recipes.
+
+${Build} :
+	mkdir -p ${Build}
+
+%.tex : %.fig | ${Build}
+	fig2dev -L eepic $< > ${Build}/$@
+
+%.ps : %.fig | ${Build}
+	fig2dev -L ps $< > ${Build}/$@
+
+%.pstex : %.fig | ${Build}
+	fig2dev -L pstex $< > ${Build}/$@
+	fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
+
+# Local Variables: #
+# compile-command: "make" #
+# End: #
Index: doc/theses/fangren_yu_COOP_S20/Report.tex
===================================================================
--- doc/theses/fangren_yu_COOP_S20/Report.tex	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
+++ doc/theses/fangren_yu_COOP_S20/Report.tex	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -0,0 +1,654 @@
+\documentclass[twoside,12pt]{article}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Latex packages used in the document.
+\usepackage{fullpage,times,comment}
+\usepackage{epic,eepic}
+\usepackage{upquote}									% switch curled `'" to straight
+\usepackage{calc}
+\usepackage{varioref}									% extended references
+\usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt]{subfig}
+\renewcommand{\thesubfigure}{\alph{subfigure})}
+\usepackage{latexsym}                                   % \Box glyph
+\usepackage{mathptmx}                                   % better math font with "times"
+\usepackage[usenames]{color}
+\input{common}                                          % common CFA document macros
+\usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
+\usepackage{breakurl}
+
+\usepackage[pagewise]{lineno}
+\renewcommand{\linenumberfont}{\scriptsize\sffamily}
+
+% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
+% removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
+% AFTER HYPERREF.
+\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
+\newcommand{\NOTE}{\textbf{NOTE}}
+
+\setlength{\topmargin}{-0.45in}							% move running title into header
+\setlength{\headsep}{0.25in}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\CFADefaults
+\lstset{
+language=C++,											% make C++ the default language
+escapechar=\$,											% LaTeX escape in CFA code
+moredelim=**[is][\color{red}]{`}{`},
+}% lstset
+\lstMakeShortInline@%
+\lstnewenvironment{C++}[1][]                            % use C++ style
+{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`},#1}}
+{}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\setcounter{secnumdepth}{3}                             % number subsubsections
+\setcounter{tocdepth}{3}                                % subsubsections in table of contents
+\makeindex
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\title{\Huge
+cfa-cc Developer's Reference
+}% title
+
+\author{\LARGE
+Fangren Yu
+}% author
+
+\date{
+\today
+}% date
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\begin{document}
+\pagestyle{headings}
+% changed after setting pagestyle
+\renewcommand{\sectionmark}[1]{\markboth{\thesection\quad #1}{\thesection\quad #1}}
+\renewcommand{\subsectionmark}[1]{\markboth{\thesubsection\quad #1}{\thesubsection\quad #1}}
+\pagenumbering{roman}
+\linenumbers                                            % comment out to turn off line numbering
+
+\maketitle
+\pdfbookmark[1]{Contents}{section}
+\tableofcontents
+
+\clearpage
+\thispagestyle{plain}
+\pagenumbering{arabic}
+
+
+\section{Overview}
+
+cfa-cc is the reference compiler for the \CFA programming language, which is a non-
+object-oriented extension to C.
+\CFA attempts to introduce productive modern programming language features to C
+while maintaining as much backward-compatibility as possible, so that most existing C
+programs can seamlessly work with \CFA.
+
+Since the \CFA project was dated back to the early 2000s, and only restarted in the past
+few years, there is a significant amount of legacy code in the current compiler codebase,
+with little proper documentation available. This becomes a difficulty while developing new
+features based on the previous implementations, and especially while diagnosing
+problems.
+
+Currently, the \CFA team is also facing another problem: bad compiler performance. For
+the development of a new programming language, writing a standard library is an
+important part. The incompetence of the compiler causes building the library files to take
+tens of minutes, making iterative development and testing almost impossible. There is
+ongoing effort to rewrite the core data structure of the compiler to overcome the
+performance issue, but many bugs may appear during the work, and lack of documentation
+makes debugging extremely difficult.
+
+This developer's reference will be continuously improved and eventually cover the
+compiler codebase. For now, the focus is mainly on the parts being rewritten, and also the
+performance bottleneck, namely the resolution algorithm. It is aimed to provide new
+developers to the project enough guidance and clarify the purposes and behavior of certain
+functions which are not mentioned in the previous \CFA research papers.
+
+
+\section{Compiler Framework}
+
+\subsection{AST Representation}
+
+Source code input is first transformed into abstract syntax tree (AST) representation by the
+parser before analyzed by the compiler.
+
+There are 4 major categories of AST nodes used by the compiler, along with some derived
+structures.
+
+\subsubsection{Declaration nodes}
+
+A declaration node represents either of:
+\begin{itemize}
+\item
+Type declaration: struct, union, typedef or type parameter (see Appendix A.3)
+\item
+Variable declaration
+\item
+Function declaration
+\end{itemize}
+Declarations are introduced by standard C declarations, with the usual scoping rules.
+In addition, declarations can also be introduced by the forall clause (which is the origin
+of \CFA's name):
+\begin{cfa}
+forall (<$\emph{TypeParameterList}$> | <$\emph{AssertionList}$>)
+	$\emph{declaration}$
+\end{cfa}
+Type parameters in \CFA are similar to \CC template type parameters. The \CFA
+declaration
+\begin{cfa}
+forall (dtype T) ...
+\end{cfa}
+behaves similarly as the \CC template declaration
+\begin{C++}
+template <typename T> ...
+\end{C++}
+
+Assertions are a distinctive feature of \CFA: contrary to the \CC template where
+arbitrary functions and operators can be used in a template definition, in a \CFA
+parametric function, operations on parameterized types must be declared in assertions.
+
+Consider the following \CC template:
+\begin{C++}
+template <typename T> int foo(T t) {
+	return bar(t) + baz(t);
+}
+\end{C++}
+Unless bar and baz are also parametric functions taking any argument type, they must be
+declared in the assertions, or otherwise the code will not compile:
+\begin{cfa}
+forall (dtype T | { int bar(T); int baz(t); }) int foo (T t) {
+	return bar(t) + baz(t);
+}
+\end{cfa}
+Assertions are written using the usual function declaration syntax. The scope of type
+parameters and assertions is the following declaration.
+
+\subsubsection{Type nodes}
+
+A type node represents the type of an object or expression.
+Named types reference the corresponding type declarations. The type of a function is its
+function pointer type (same as standard C).
+With the addition of type parameters, named types may contain a list of parameter values
+(actual parameter types).
+
+\subsubsection{Statement nodes}
+
+Statement nodes represent the statements in the program, including basic expression
+statements, control flows and blocks.
+Local declarations (within a block statement) are represented as declaration statements.
+
+\subsubsection{Expression nodes}
+
+Some expressions are represented differently in the compiler before and after resolution
+stage:
+\begin{itemize}
+\item
+Name expressions: NameExpr pre-resolution, VariableExpr post-resolution
+\item
+Member expressions: UntypedMemberExpr pre-resolution, MemberExpr post-resolution
+\item
+Function call expressions (including overloadable operators): UntypedExpr pre-resolution, ApplicationExpr post-resolution
+\end{itemize}
+The pre-resolution representations contain only the symbols. Post-resolution results link
+them to the actual variable and function declarations.
+
+
+\subsection{Compilation Passes}
+
+Compilation steps are implemented as passes, which follows a general structural recursion
+pattern on the syntax tree.
+
+The basic work flow of compilation passes follows preorder and postorder traversal on
+tree data structure, implemented with visitor pattern, and can be loosely described with
+the following pseudocode:
+\begin{C++}
+Pass::visit (node_t node) {
+	previsit(node);
+	if (visit_children)
+		for each child of node:
+			child.accept(this);
+	postvisit(node);
+}
+\end{C++}
+Operations in previsit() happen in preorder (top to bottom) and operations in
+postvisit() happen in postorder (bottom to top). The precise order of recursive
+operations on child nodes can be found in @Common/PassVisitor.impl.h@ (old) and
+@AST/Pass.impl.hpp@ (new).
+Implementations of compilation passes need to follow certain conventions:
+\begin{itemize}
+\item
+Passes \textbf{should not} directly override the visit method (Non-virtual Interface
+principle); if a pass desires different recursion behavior, it should set
+@visit_children@ to false and perform recursive calls manually within previsit or
+postvisit procedures. To enable this option, inherit from @WithShortCircuiting@ mixin.
+\item
+previsit may mutate the node but \textbf{must not} change the node type or return null.
+\item
+postvisit may mutate the node, reconstruct it to a different node type, or delete it by
+returning null.
+\item
+If the previsit or postvisit method is not defined for a node type, the step is skipped.
+If the return type is declared as void, the original node is returned by default. These
+behaviors are controlled by template specialization rules; see
+@Common/PassVisitor.proto.h@ (old) and @AST/Pass.proto.hpp@ (new) for details.
+\end{itemize}
+Other useful mixin classes for compilation passes include:
+\begin{itemize}
+\item
+WithGuards allows saving values of variables and restore automatically upon exiting
+the current node.
+\item
+WithVisitorRef creates a wrapped entity of current pass (the actual argument
+passed to recursive calls internally) for explicit recursion, usually used together
+with WithShortCircuiting.
+\item
+WithSymbolTable gives a managed symbol table with built-in scoping rule handling
+(\eg on entering and exiting a block statement)
+\end{itemize}
+\NOTE: If a pass extends the functionality of another existing pass, due to \CC overloading
+resolution rules, it \textbf{must} explicitly introduce the inherited previsit and postvisit procedures
+to its own scope, or otherwise they will not be picked up by template resolution:
+\begin{C++}
+class Pass2: public Pass1 {
+	using Pass1::previsit;
+	using Pass1::postvisit;
+	// new procedures
+}
+\end{C++}
+
+
+\subsection{Data Structure Change WIP (new-ast)}
+
+It has been observed that excessive copying of syntax tree structures accounts for a
+majority of computation cost and significantly slows down the compiler. In the previous
+implementation of the syntax tree, every internal node has a unique parent; therefore all
+copies are required to duplicate everything down to the bottom. A new, experimental
+re-implementation of the syntax tree (source under directory AST/ hereby referred to as
+``new-ast'') attempts to overcome this issue with a functional approach that allows sharing
+of common sub-structures and only makes copies when necessary.
+
+The core of new-ast is a customized implementation of smart pointers, similar to
+@std::shared_ptr@ and @std::weak_ptr@ in \CC standard library. Reference counting is
+used to detect sharing and allows optimization. For a purely functional (a.k.a. immutable)
+data structure, all mutations are modelled by shallow copies along the path of mutation.
+With reference counting optimization, unique nodes are allowed to be mutated in place.
+This however, may potentially introduce some complications and bugs; a few issues are
+discussed near the end of this section.
+
+\subsubsection{Source: AST/Node.hpp}
+
+class @ast::Node@ is the base class of all new-ast node classes, which implements
+reference counting mechanism. Two different counters are recorded: ``strong'' reference
+count for number of nodes semantically owning it; ``weak'' reference count for number of
+nodes holding a mere reference and only need to observe changes.
+class @ast::ptr_base@ is the smart pointer implementation and also takes care of
+resource management.
+
+Direct access through the smart pointer is read-only. A mutable access should be obtained
+by calling shallowCopy or mutate as below.
+
+Currently, the weak pointers are only used to reference declaration nodes from a named
+type, or a variable expression. Since declaration nodes are intended to denote unique
+entities in the program, weak pointers always point to unique (unshared) nodes. This may
+change in the future, and weak references to shared nodes may introduce some problems;
+see mutate function below.
+
+All node classes should always use smart pointers in the structure and should not use raw
+pointers.
+
+\begin{C++}
+void ast::Node::increment(ref_type ref)
+\end{C++}
+Increments this node's strong or weak reference count.
+\begin{C++}
+void ast::Node::decrement(ref_type ref, bool do_delete = true)
+\end{C++}
+Decrements this node's strong or weak reference count. If strong reference count reaches
+zero, the node is deleted by default.
+\NOTE: Setting @do_delete@ to false may result in a detached node. Subsequent code should
+manually delete the node or assign it to a strong pointer to prevent memory leak.
+Reference counting functions are internally called by @ast::ptr_base@.
+\begin{C++}
+template<typename node_t>
+node_t * shallowCopy(const node_t * node)
+\end{C++}
+Returns a mutable, shallow copy of node: all child pointers are pointing to the same child
+nodes.
+\begin{C++}
+template<typename node_t>
+node_t * mutate(const node_t * node)
+\end{C++}
+If node is unique (strong reference count is 1), returns a mutable pointer to the same node.
+Otherwise, returns shallowCopy(node).
+It is an error to mutate a shared node that is weak-referenced. Currently this does not
+happen. The problem may appear once weak pointers to shared nodes (\eg expression
+nodes) are used; special care will be needed.
+
+\NOTE: This naive uniqueness check may not be sufficient in some cases. A discussion of the
+issue is presented at the end of this section.
+\begin{C++}
+template<typename node_t, typename parent_t, typename field_t, typename assn_t>
+const node_t * mutate_field(const node_t * node, field_t parent_t::*field, assn_t && val)
+\end{C++}
+\begin{C++}
+template<typename node_t, typename parent_t, typename coll_t, typename ind_t,
+		typename field_t>
+const node_t * mutate_field_index(const node_t * node, coll_t parent_t::* field, ind_t i,
+		field_t && val)
+\end{C++}
+Helpers for mutating a field on a node using pointer to member (creates shallow copy
+when necessary).
+
+\subsubsection{Issue: Undetected sharing}
+
+The @mutate@ behavior described above has a problem: deeper shared nodes may be
+mistakenly considered as unique. \VRef[Figure]{f:DeepNodeSharing} shows how the problem could arise:
+\begin{figure}
+\centering
+\input{DeepNodeSharing}
+\caption{Deep sharing of nodes}
+\label{f:DeepNodeSharing}
+\end{figure}
+Suppose that we are working on the tree rooted at P1, which
+is logically the chain P1-A-B and P2 is irrelevant, and then
+mutate(B) is called. The algorithm considers B as unique since
+it is only directly owned by A. However, the other tree P2-A-B
+indirectly shares the node B and is therefore wrongly mutated.
+
+To partly address this problem, if the mutation is called higher up the tree, a chain
+mutation helper can be used:
+
+\subsubsection{Source: AST/Chain.hpp}
+
+\begin{C++}
+template<typename node_t, Node::ref_type ref_t>
+auto chain_mutate(ptr_base<node_t, ref_t> & base)
+\end{C++}
+This function returns a chain mutator handle which takes pointer-to-member to go down
+the tree while creating shallow copies as necessary; see @struct _chain_mutator@ in the
+source code for details.
+
+For example, in the above diagram, if mutation of B is wanted while at P1, the call using
+@chain_mutate@ looks like the following:
+\begin{C++}
+chain_mutate(P1.a)(&A.b) = new_value_of_b;
+\end{C++}
+Note that if some node in chain mutate is shared (therefore shallow copied), it implies that
+every node further down will also be copied, thus correctly executing the functional
+mutation algorithm. This example code creates copies of both A and B and performs
+mutation on the new nodes, so that the other tree P2-A-B is untouched.
+However, if a pass traverses down to node B and performs mutation, for example, in
+@postvisit(B)@, information on sharing higher up is lost. Since the new-ast structure is only in
+experimental use with the resolver algorithm, which mostly rebuilds the tree bottom-up,
+this issue does not actually happen. It should be addressed in the future when other
+compilation passes are migrated to new-ast and many of them contain procedural
+mutations, where it might cause accidental mutations to other logically independent trees
+(\eg common sub-expression) and become a bug.
+
+
+\vspace*{20pt} % FIX ME, spacing problem with this heading ???
+\section{Compiler Algorithm Documentation}
+
+This documentation currently covers most of the resolver, data structures used in variable
+and expression resolution, and a few directly related passes. Later passes involving code
+generation is not included yet; documentation for those will be done afterwards.
+
+\subsection{Symbol Table}
+
+\NOTE: For historical reasons, the symbol table data structure was called ``indexer'' in the
+old implementation. Hereby we will be using the name SymbolTable everywhere.
+The symbol table stores a mapping from names to declarations and implements a similar
+name space separation rule, and the same scoping rules in standard C.\footnote{ISO/IEC 9899:1999, Sections 6.2.1 and 6.2.3} The difference in
+name space rule is that typedef aliases are no longer considered ordinary identifiers.
+In addition to C tag types (struct, union, enum), \CFA introduces another tag type, trait,
+which is a named collection of assertions.
+
+\subsubsection{Source: AST/SymbolTable.hpp}
+
+\subsubsection{Source: SymTab/Indexer.h}
+
+\begin{C++}
+SymbolTable::addId(const DeclWithType * decl)
+\end{C++}
+Since \CFA allows overloading of variables and functions, ordinary identifier names need
+to be mangled. The mangling scheme is closely based on the Itanium \CC ABI,\footnote{\url{https://itanium-cxx-abi.github.io/cxx-abi/abi.html}, Section 5.1} while
+making adaptations to \CFA specific features, mainly assertions and overloaded variables
+by type. Naming conflicts are handled by mangled names; lookup by name returns a list of
+declarations with the same literal identifier name.
+
+\begin{C++}
+SymbolTable::addStruct(const StructDecl * decl)
+SymbolTable::addUnion(const UnionDecl * decl)
+SymbolTable::addEnum(const EnumDecl * decl)
+SymbolTable::addTrait(const TraitDecl * decl)
+\end{C++}
+Adds a tag type declaration to the symbol table.
+\begin{C++}
+SymbolTable::addType(const NamedTypeDecl * decl)
+\end{C++}
+Adds a typedef alias to the symbol table.
+
+\textbf{C Incompatibility Note}: Since Cforall allows using struct, union and enum type names
+without the keywords, typedef names and tag type names cannot be disambiguated by
+syntax rules. Currently the compiler puts them together and disallows collision. The
+following program is valid C but not valid Cforall:
+\begin{C++}
+struct A {};
+typedef int A;
+// gcc: ok, cfa: Cannot redefine typedef A
+\end{C++}
+In actual practices however, such usage is extremely rare, and typedef struct A A; is
+not considered an error, but silently discarded. Therefore, we expect this change to have
+minimal impact on existing C programs.
+Meanwhile, the following program is allowed in Cforall:
+\begin{C++}
+typedef int A;
+void A();
+// gcc: A redeclared as different kind of symbol, cfa: ok
+\end{C++}
+
+\subsection{Type Environment and Unification}
+
+The core of parametric type resolution algorithm.
+Type Environment organizes type parameters in \textbf{equivalent classes} and maps them to
+actual types. Unification is the algorithm that takes two (possibly parametric) types and
+parameter mappings and attempts to produce a common type by matching the type
+environments.
+
+The unification algorithm is recursive in nature and runs in two different modes internally:
+\begin{itemize}
+\item
+\textbf{Exact} unification mode requires equivalent parameters to match perfectly;
+\item
+\textbf{Inexact} unification mode allows equivalent parameters to be converted to a
+common type.
+\end{itemize}
+For a pair of matching parameters (actually, their equivalent classes), if either side is open
+(not bound to a concrete type yet), they are simply combined.
+
+Within inexact mode, types are allowed to differ on their cv-qualifiers; additionally, if a
+type never appear either in parameter list or as the base type of a pointer, it may also be
+widened (i.e. safely converted). As Cforall currently does not implement subclassing similar
+to object-oriented languages, widening conversions are on primitive types only, for
+example the conversion from int to long.
+
+The need for two unification modes come from the fact that parametric types are
+considered compatible only if all parameters are exactly the same (not just compatible).
+Pointer types also behaves similarly; in fact, they may be viewed as a primitive kind of
+parametric types. @int*@ and @long*@ are different types, just like @vector(int)@ and
+@vector(long)@ are, for the parametric type @vector(T)@.
+
+The resolver should use the following ``@public@'' functions:\footnote{
+Actual code also tracks assertions on type parameters; those extra arguments are omitted here for
+conciseness.}
+
+
+\subsubsection{Source: ResolvExpr/Unify.cc}
+
+\begin{C++}
+bool unify(const Type *type1, const Type *type2, TypeEnvironment &env,
+OpenVarSet &openVars, const SymbolTable &symtab, Type *&commonType)
+\end{C++}
+Attempts to unify @type1@ and @type2@ with current type environment.
+
+If operation succeeds, @env@ is modified by combining the equivalence classes of matching
+parameters in @type1@ and @type2@, and their common type is written to commonType.
+
+If operation fails, returns false.
+\begin{C++}
+bool typesCompatible(const Type * type1, const Type * type2, const
+SymbolTable &symtab, const TypeEnvironment &env)
+bool typesCompatibleIgnoreQualifiers(const Type * type1, const Type *
+type2, const SymbolTable &symtab, const TypeEnvironment &env)
+\end{C++}
+
+Determines if type1 and type2 can possibly be the same type. The second version ignores
+the outermost cv-qualifiers if present.\footnote{
+In const \lstinline@int * const@, only the second \lstinline@const@ is ignored.}
+
+The call has no side effect.
+
+\NOTE: No attempts are made to widen the types (exact unification is used), although the
+function names may suggest otherwise. E.g. @typesCompatible(int, long)@ returns false.
+
+
+\subsection{Expression Resolution}
+
+The design of the current version of expression resolver is outlined in the Ph.D. Thesis from
+Aaron Moss~\cite{Moss19}.
+
+A summary of the resolver algorithm for each expression type is presented below.
+
+All overloadable operators are modelled as function calls. For a function call,
+interpretations of the function and arguments are found recursively. Then the following
+steps produce a filtered list of valid interpretations:
+\begin{enumerate}
+\item
+From all possible combinations of interpretations of the function and arguments,
+those where argument types may be converted to function parameter types are
+considered valid.
+\item
+Valid interpretations with the minimum sum of argument costs are kept.
+\item
+Argument costs are then discarded; the actual cost for the function call expression is
+the sum of conversion costs from the argument types to parameter types.
+\item
+For each return type, the interpretations with satisfiable assertions are then sorted
+by actual cost computed in step 3. If for a given type, the minimum cost
+interpretations are not unique, it is said that for that return type the interpretation
+is ambiguous. If the minimum cost interpretation is unique but contains an
+ambiguous argument, it is also considered ambiguous.
+\end{enumerate}
+Therefore, for each return type, the resolver produces either of:
+\begin{itemize}
+\item
+No alternatives
+\item
+A single valid alternative
+\item
+An ambiguous alternative
+\end{itemize}
+Note that an ambiguous alternative may be discarded at the parent expressions because a
+different return type matches better for the parent expressions.
+
+The non-overloadable expressions in Cforall are: cast expressions, address-of (unary @&@)
+expressions, short-circuiting logical expressions (@&&@, @||@) and ternary conditional
+expression (@?:@).
+
+For a cast expression, the convertible argument types are kept. Then the result is selected
+by lowest argument cost, and further by lowest conversion cost to target type. If the lowest
+cost is still not unique, or an ambiguous argument interpretation is selected, the cast
+expression is ambiguous. In an expression statement, the top level expression is implicitly
+cast to void.
+
+For an address-of expression, only lvalue results are kept and the minimum cost is selected.
+
+For logical expressions @&&@ and @||@, arguments are implicitly cast to bool, and follow the rule
+of cast expression as above.
+
+For the ternary conditional expression, the condition is implicitly cast to bool, and the
+branch expressions must have compatible types. Each pair of compatible branch
+expression types produce a possible interpretation, and the cost is defined as the sum of
+expression costs plus the sum of conversion costs to the common type.
+
+TODO: Write a specification for expression costs.
+
+
+\subsection{Assertion Satisfaction}
+
+The resolver tries to satisfy assertions on expressions only when it is needed: either while
+selecting from multiple alternatives of a same result type for a function call (step 4 of
+resolving function calls), or upon reaching the top level of an expression statement.
+
+Unsatisfiable alternatives are discarded. Satisfiable alternatives receive \textbf{implicit
+parameters}: in Cforall, parametric functions are designed such that they can be compiled
+separately, as opposed to \CC templates which are only compiled at instantiation. Given a
+parametric function definition:
+\begin{C++}
+forall (otype T | {void foo(T);})
+void bar (T t) { foo(t); }
+\end{C++}
+The function bar does not know which @foo@ to call when compiled without knowing the call
+site, so it requests a function pointer to be passed as an extra argument. At the call site,
+implicit parameters are automatically inserted by the compiler.
+
+\textbf{TODO}: Explain how recursive assertion satisfaction and polymorphic recursion work.
+
+
+\section{Tests}
+
+\subsection{Test Suites}
+
+Automatic test suites are located under the @tests/@ directory. A test case consists of an
+input CFA source file (name ending with @.cfa@), and an expected output file located
+in @.expect/@ directory relative to the source file, with the same file name ending with @.txt@.
+So a test named @tuple/tupleCast@ has the following files, for example:
+\begin{C++}
+tests/
+..     tuple/
+......     .expect/
+..........       tupleCast.txt
+......     tupleCast.cfa
+\end{C++}
+If compilation fails, the error output is compared to the expect file. If compilation succeeds,
+the built program is run and its output compared to the expect file.
+To run the tests, execute the test script @test.py@ under the @tests/@ directory, with a list of
+test names to be run, or @--all@ to run all tests. The test script reports test cases
+fail/success, compilation time and program run time.
+
+
+\subsection{Performance Reports}
+
+To turn on performance reports, pass @-S@ flag to the compiler.
+
+3 kinds of performance reports are available:
+\begin{enumerate}
+\item
+Time, reports time spent in each compilation step
+\item
+Heap, reports number of dynamic memory allocations, total bytes allocated, and
+maximum heap memory usage
+\item
+Counters, for certain predefined statistics; counters can be registered anywhere in
+the compiler as a static object, and the interface can be found at
+@Common/Stats/Counter.h@.
+\end{enumerate}
+It is suggested to run performance tests with optimized build (@g++@ flag @-O3@)
+
+
+\bibliographystyle{plain}
+\bibliography{pl}
+
+
+\end{document}
+
+% Local Variables: %
+% tab-width: 4 %
+% fill-column: 100 %
+% compile-command: "make" %
+% End: %
Index: doc/theses/fangren_yu_COOP_S20/figures/DeepNodeSharing.fig
===================================================================
--- doc/theses/fangren_yu_COOP_S20/figures/DeepNodeSharing.fig	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
+++ doc/theses/fangren_yu_COOP_S20/figures/DeepNodeSharing.fig	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -0,0 +1,25 @@
+#FIG 3.2  Produced by xfig version 3.2.5c
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1800 1950 150 150 1800 1950 1950 1950
+1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1800 2550 150 150 1800 2550 1950 2550
+1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 2250 1350 150 150 2250 1350 2400 1350
+1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1350 1350 150 150 1350 1350 1500 1350
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 1350 1500 1800 1800
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 2250 1500 1800 1800
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 1800 2100 1800 2400
+4 1 0 50 -1 0 12 0.0000 2 135 210 1350 1425 P1\001
+4 1 0 50 -1 0 12 0.0000 2 135 210 2250 1425 P2\001
+4 1 0 50 -1 0 12 0.0000 2 135 135 1800 2025 A\001
+4 1 0 50 -1 0 12 0.0000 2 135 135 1800 2625 B\001
+4 0 0 50 -1 0 12 0.0000 2 135 675 2100 2625 count: 1\001
+4 0 0 50 -1 0 12 0.0000 2 135 675 2100 2025 count: 2\001
Index: doc/theses/fangren_yu_COOP_S20/figures/DeepNodeSharing.fig.bak
===================================================================
--- doc/theses/fangren_yu_COOP_S20/figures/DeepNodeSharing.fig.bak	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
+++ doc/theses/fangren_yu_COOP_S20/figures/DeepNodeSharing.fig.bak	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -0,0 +1,23 @@
+#FIG 3.2  Produced by xfig version 3.2.5c
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1800 1950 150 150 1800 1950 1950 1950
+1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1800 2550 150 150 1800 2550 1950 2550
+1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 2250 1350 150 150 2250 1350 2400 1350
+1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1350 1350 150 150 1350 1350 1500 1350
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 1350 1500 1800 1800
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 2250 1500 1800 1800
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 1800 2100 1800 2400
+4 1 0 50 -1 0 12 0.0000 2 135 210 1350 1425 P1\001
+4 1 0 50 -1 0 12 0.0000 2 135 210 2250 1425 P2\001
+4 1 0 50 -1 0 12 0.0000 2 135 135 1800 2025 A\001
+4 1 0 50 -1 0 12 0.0000 2 135 135 1800 2625 B\001
Index: libcfa/src/Makefile.am
===================================================================
--- libcfa/src/Makefile.am	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ libcfa/src/Makefile.am	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -62,4 +62,5 @@
 	iterator.hfa \
 	limits.hfa \
+	memory.hfa \
 	parseargs.hfa \
 	rational.hfa \
Index: libcfa/src/concurrency/monitor.cfa
===================================================================
--- libcfa/src/concurrency/monitor.cfa	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ libcfa/src/concurrency/monitor.cfa	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -89,5 +89,8 @@
 	__cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
 
-	if( !this->owner ) {
+	if( unlikely(0 != (0x1 & (uintptr_t)this->owner)) ) {
+		abort( "Attempt by thread \"%.256s\" (%p) to access joined monitor %p.", thrd->self_cor.name, thrd, this );
+	}
+	else if( !this->owner ) {
 		// No one has the monitor, just take it
 		__set_owner( this, thrd );
@@ -137,5 +140,5 @@
 }
 
-static void __dtor_enter( $monitor * this, fptr_t func ) {
+static void __dtor_enter( $monitor * this, fptr_t func, bool join ) {
 	// Lock the monitor spinlock
 	lock( this->lock __cfaabi_dbg_ctx2 );
@@ -157,8 +160,22 @@
 		return;
 	}
-	else if( this->owner == thrd) {
+	else if( this->owner == thrd && !join) {
 		// We already have the monitor... but where about to destroy it so the nesting will fail
 		// Abort!
 		abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd );
+	}
+	// SKULLDUGGERY: join will act as a dtor so it would normally trigger to above check
+	// to avoid that it sets the owner to the special value thrd | 1p before exiting
+	else if( this->owner == ($thread*)(1 | (uintptr_t)thrd) ) {
+		// restore the owner and just return
+		__cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);
+
+		// No one has the monitor, just take it
+		this->owner = thrd;
+
+		verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
+
+		unlock( this->lock );
+		return;
 	}
 
@@ -251,13 +268,15 @@
 
 // Leave single monitor for the last time
-void __dtor_leave( $monitor * this ) {
+void __dtor_leave( $monitor * this, bool join ) {
 	__cfaabi_dbg_debug_do(
 		if( TL_GET( this_thread ) != this->owner ) {
 			abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner);
 		}
-		if( this->recursion != 1 ) {
+		if( this->recursion != 1  && !join ) {
 			abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
 		}
 	)
+
+	this->owner = ($thread*)(1 | (uintptr_t)this->owner);
 }
 
@@ -307,4 +326,15 @@
 }
 
+// Join a thread
+forall( dtype T | is_thread(T) )
+T & join( T & this ) {
+	$monitor *    m = get_monitor(this);
+	void (*dtor)(T& mutex this) = ^?{};
+	monitor_dtor_guard_t __guard = { &m, (fptr_t)dtor, true };
+	{
+		return this;
+	}
+}
+
 // Enter multiple monitor
 // relies on the monitor array being sorted
@@ -366,5 +396,5 @@
 // Ctor for monitor guard
 // Sorts monitors before entering
-void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {
+void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func, bool join ) {
 	// optimization
 	$thread * thrd = TL_GET( this_thread );
@@ -376,8 +406,11 @@
 	this.prev = thrd->monitors;
 
+	// Save whether we are in a join or not
+	this.join = join;
+
 	// Update thread context (needed for conditions)
 	(thrd->monitors){m, 1, func};
 
-	__dtor_enter( this.m, func );
+	__dtor_enter( this.m, func, join );
 }
 
@@ -385,5 +418,5 @@
 void ^?{}( monitor_dtor_guard_t & this ) {
 	// Leave the monitors in order
-	__dtor_leave( this.m );
+	__dtor_leave( this.m, this.join );
 
 	// Restore thread context
Index: libcfa/src/concurrency/monitor.hfa
===================================================================
--- libcfa/src/concurrency/monitor.hfa	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ libcfa/src/concurrency/monitor.hfa	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -53,7 +53,8 @@
 	$monitor *    m;
 	__monitor_group_t prev;
+	bool join;
 };
 
-void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)() );
+void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)(), bool join );
 void ^?{}( monitor_dtor_guard_t & this );
 
Index: libcfa/src/concurrency/thread.hfa
===================================================================
--- libcfa/src/concurrency/thread.hfa	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ libcfa/src/concurrency/thread.hfa	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -106,4 +106,9 @@
 void sleep( Duration duration );
 
+//----------
+// join
+forall( dtype T | is_thread(T) )
+T & join( T & this );
+
 // Local Variables: //
 // mode: c //
Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/AST/Convert.cpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -1162,5 +1162,5 @@
 	}
 
-	const ast::Type * postvisit( const ast::ReferenceToType * old, ReferenceToType * ty ) {
+	const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) {
 		ty->forall = get<TypeDecl>().acceptL( old->forall );
 		ty->parameters = get<Expression>().acceptL( old->params );
@@ -2521,5 +2521,5 @@
 	}
 
-	void postvisit( const ReferenceToType * old, ast::ReferenceToType * ty ) {
+	void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) {
 		ty->forall = GET_ACCEPT_V( forall, TypeDecl );
 		ty->params = GET_ACCEPT_V( parameters, Expr );
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/AST/Fwd.hpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -107,5 +107,5 @@
 class QualifiedType;
 class FunctionType;
-class ReferenceToType;
+class BaseInstType;
 template<typename decl_t> class SueInstType;
 using StructInstType = SueInstType<StructDecl>;
Index: src/AST/GenericSubstitution.cpp
===================================================================
--- src/AST/GenericSubstitution.cpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/AST/GenericSubstitution.cpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -42,5 +42,5 @@
 	private:
 		// make substitution for generic type
-		void makeSub( const ReferenceToType * ty ) {
+		void makeSub( const BaseInstType * ty ) {
 			visit_children = false;
 			const AggregateDecl * aggr = ty->aggr();
Index: src/AST/Node.cpp
===================================================================
--- src/AST/Node.cpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/AST/Node.cpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -266,6 +266,6 @@
 template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::weak >;
 template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::strong >;
-template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::weak >;
-template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::strong >;
 template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::weak >;
 template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::strong >;
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/AST/Pass.hpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -118,4 +118,5 @@
 
 	// Versions of the above for older compilers.
+	template< typename... Args >
 	static void run( std::list< ptr<Decl> > & decls ) {
 		Pass<core_t> visitor;
@@ -123,7 +124,8 @@
 	}
 
-	static auto read( Node const * node ) {
+	template< typename node_type, typename... Args >
+	static auto read( node_type const * node ) {
 		Pass<core_t> visitor;
-		Node const * temp = node->accept( visitor );
+		node_type const * temp = node->accept( visitor );
 		assert( temp == node );
 		return visitor.get_result();
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/AST/Print.cpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -270,5 +270,5 @@
 	}
 
-	void preprint( const ast::ReferenceToType * node ) {
+	void preprint( const ast::BaseInstType * node ) {
 		print( node->forall );
 		print( node->attributes );
Index: src/AST/SymbolTable.cpp
===================================================================
--- src/AST/SymbolTable.cpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/AST/SymbolTable.cpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -313,5 +313,5 @@
 		if ( ! expr->result ) continue;
 		const Type * resTy = expr->result->stripReferences();
-		auto aggrType = dynamic_cast< const ReferenceToType * >( resTy );
+		auto aggrType = dynamic_cast< const BaseInstType * >( resTy );
 		assertf( aggrType, "WithStmt expr has non-aggregate type: %s",
 			toString( expr->result ).c_str() );
@@ -654,5 +654,5 @@
 			if ( dwt->name == "" ) {
 				const Type * t = dwt->get_type()->stripReferences();
-				if ( auto rty = dynamic_cast<const ReferenceToType *>( t ) ) {
+				if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {
 					if ( ! dynamic_cast<const StructInstType *>(rty)
 						&& ! dynamic_cast<const UnionInstType *>(rty) ) continue;
Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/AST/Type.cpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -124,12 +124,12 @@
 }
 
-// --- ReferenceToType
-
-void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {
+// --- BaseInstType
+
+void BaseInstType::initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub ) {
 	ParameterizedType::initWithSub( o, sub ); // initialize substitution
 	params = sub.core( o.params );            // apply to parameters
 }
 
-ReferenceToType::ReferenceToType( const ReferenceToType & o )
+BaseInstType::BaseInstType( const BaseInstType & o )
 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ), 
   hoistType( o.hoistType ) {
@@ -138,5 +138,5 @@
 }
 
-std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
+std::vector<readonly<Decl>> BaseInstType::lookup( const std::string& name ) const {
 	assertf( aggr(), "Must have aggregate to perform lookup" );
 
@@ -153,5 +153,5 @@
 SueInstType<decl_t>::SueInstType(
 	const decl_t * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
-: ReferenceToType( b->name, q, move(as) ), base( b ) {}
+: BaseInstType( b->name, q, move(as) ), base( b ) {}
 
 template<typename decl_t>
@@ -168,10 +168,10 @@
 TraitInstType::TraitInstType(
 	const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
-: ReferenceToType( b->name, q, move(as) ), base( b ) {}
+: BaseInstType( b->name, q, move(as) ), base( b ) {}
 
 // --- TypeInstType
 
 TypeInstType::TypeInstType( const TypeInstType & o )
-: ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
+: BaseInstType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
 	Pass< ForallSubstitutor > sub;
 	initWithSub( o, sub );      // initialize substitution
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/AST/Type.hpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -329,8 +329,8 @@
 
 /// base class for types that refer to types declared elsewhere (aggregates and typedefs)
-class ReferenceToType : public ParameterizedType {
+class BaseInstType : public ParameterizedType {
 protected:
 	/// Initializes forall and parameters based on substitutor
-	void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );
+	void initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub );
 public:
 	std::vector<ptr<Expr>> params;
@@ -338,9 +338,9 @@
 	bool hoistType = false;
 
-	ReferenceToType(
+	BaseInstType(
 		const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
 	: ParameterizedType(q, std::move(as)), params(), name(n) {}
 
-	ReferenceToType( const ReferenceToType & o );
+	BaseInstType( const BaseInstType & o );
 
 	/// Gets aggregate declaration this type refers to
@@ -350,5 +350,5 @@
 
 private:
-	virtual ReferenceToType * clone() const override = 0;
+	virtual BaseInstType * clone() const override = 0;
 	MUTATE_FRIEND
 };
@@ -356,5 +356,5 @@
 // Common implementation for the SUE instance types. Not to be used directly.
 template<typename decl_t>
-class SueInstType final : public ReferenceToType {
+class SueInstType final : public BaseInstType {
 public:
 	using base_type = decl_t;
@@ -363,5 +363,5 @@
 	SueInstType(
 		const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
-	: ReferenceToType( n, q, std::move(as) ), base() {}
+	: BaseInstType( n, q, std::move(as) ), base() {}
 
 	SueInstType(
@@ -388,5 +388,5 @@
 
 /// An instance of a trait type.
-class TraitInstType final : public ReferenceToType {
+class TraitInstType final : public BaseInstType {
 public:
 	readonly<TraitDecl> base;
@@ -394,5 +394,5 @@
 	TraitInstType(
 		const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
-	: ReferenceToType( n, q, std::move(as) ), base() {}
+	: BaseInstType( n, q, std::move(as) ), base() {}
 
 	TraitInstType(
@@ -411,5 +411,5 @@
 
 /// instance of named type alias (typedef or variable)
-class TypeInstType final : public ReferenceToType {
+class TypeInstType final : public BaseInstType {
 public:
 	readonly<TypeDecl> base;
@@ -419,8 +419,8 @@
 		const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
-	: ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
+	: BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
 	TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
-	: ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
+	: BaseInstType( n, q, std::move(as) ), base(), kind( k ) {}
 
 	TypeInstType( const TypeInstType & o );
Index: src/AST/TypeSubstitution.cpp
===================================================================
--- src/AST/TypeSubstitution.cpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/AST/TypeSubstitution.cpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -176,5 +176,5 @@
 }
 
-void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {
+void TypeSubstitution::Substituter::handleAggregateType( const BaseInstType * type ) {
 	GuardValue( boundVars );
 	// bind type variables from forall-qualifiers
Index: src/AST/TypeSubstitution.hpp
===================================================================
--- src/AST/TypeSubstitution.hpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/AST/TypeSubstitution.hpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -169,5 +169,5 @@
 		void previsit( const ParameterizedType * type );
 		/// Records type variable bindings from forall-statements and instantiations of generic types
-		void handleAggregateType( const ReferenceToType * type );
+		void handleAggregateType( const BaseInstType * type );
 
 		void previsit( const StructInstType * aggregateUseType );
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/Concurrency/Keywords.cc	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -931,5 +931,6 @@
 					{
 						new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
-						new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) )
+						new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ),
+						new SingleInit( new ConstantExpr( Constant::from_bool( false ) ) )
 					},
 					noDesignators,
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -816,5 +816,5 @@
 		/// Adds aggregate member interpretations
 		void addAggMembers(
-			const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
+			const ast::BaseInstType * aggrInst, const ast::Expr * expr,
 			const Candidate & cand, const Cost & addedCost, const std::string & name
 		) {
@@ -1263,5 +1263,5 @@
 
 		void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {
-			const ast::ReferenceToType * aggInst;
+			const ast::BaseInstType * aggInst;
 			if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ;
 			else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ;
Index: src/ResolvExpr/CurrentObject.cc
===================================================================
--- src/ResolvExpr/CurrentObject.cc	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/ResolvExpr/CurrentObject.cc	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -923,5 +923,5 @@
 
 	MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
-		if ( auto aggr = dynamic_cast< const ReferenceToType * >( type ) ) {
+		if ( auto aggr = dynamic_cast< const BaseInstType * >( type ) ) {
 			if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
 				return new StructIterator{ loc, sit };
@@ -932,5 +932,5 @@
 					dynamic_cast< const EnumInstType * >( type )
 						|| dynamic_cast< const TypeInstType * >( type ),
-					"Encountered unhandled ReferenceToType in createMemberIterator: %s",
+					"Encountered unhandled BaseInstType in createMemberIterator: %s",
 						toString( type ).c_str() );
 				return new SimpleIterator{ loc, type };
@@ -965,5 +965,5 @@
 					DesignatorChain & d = *dit;
 					PRINT( std::cerr << "____actual: " << t << std::endl; )
-					if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) {
+					if ( auto refType = dynamic_cast< const BaseInstType * >( t ) ) {
 						// concatenate identical field names
 						for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/ResolvExpr/Resolver.cc	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -1259,4 +1259,5 @@
 		const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
 		const ast::CatchStmt *       previsit( const ast::CatchStmt * );
+		const ast::CatchStmt *       postvisit( const ast::CatchStmt * );
 		const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
 
@@ -1491,10 +1492,30 @@
 
 	const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
-		// TODO: This will need a fix for the decl/cond scoping problem.
+		// Until we are very sure this invarent (ifs that move between passes have thenPart)
+		// holds, check it. This allows a check for when to decode the mangling.
+		if ( auto ifStmt = catchStmt->body.as<ast::IfStmt>() ) {
+			assert( ifStmt->thenPart );
+		}
+		// Encode the catchStmt so the condition can see the declaration.
 		if ( catchStmt->cond ) {
-			ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool };
-			catchStmt = ast::mutate_field(
-				catchStmt, &ast::CatchStmt::cond,
-				findSingleExpression( catchStmt->cond, boolType, symtab ) );
+			ast::CatchStmt * stmt = mutate( catchStmt );
+			stmt->body = new ast::IfStmt( stmt->location, stmt->cond, nullptr, stmt->body );
+			stmt->cond = nullptr;
+			return stmt;
+		}
+		return catchStmt;
+	}
+
+	const ast::CatchStmt * Resolver_new::postvisit( const ast::CatchStmt * catchStmt ) {
+		// Decode the catchStmt so everything is stored properly.
+		const ast::IfStmt * ifStmt = catchStmt->body.as<ast::IfStmt>();
+		if ( nullptr != ifStmt && nullptr == ifStmt->thenPart ) {
+			assert( ifStmt->cond );
+			assert( ifStmt->elsePart );
+			ast::CatchStmt * stmt = ast::mutate( catchStmt );
+			stmt->cond = ifStmt->cond;
+			stmt->body = ifStmt->elsePart;
+			// ifStmt should be implicately deleted here.
+			return stmt;
 		}
 		return catchStmt;
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/SymTab/Mangler.cc	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -437,5 +437,5 @@
 		  private:
 			void mangleDecl( const ast::DeclWithType *declaration );
-			void mangleRef( const ast::ReferenceToType *refType, std::string prefix );
+			void mangleRef( const ast::BaseInstType *refType, std::string prefix );
 
 			void printQualifiers( const ast::Type *type );
@@ -560,5 +560,5 @@
 		}
 
-		void Mangler_new::mangleRef( const ast::ReferenceToType * refType, std::string prefix ) {
+		void Mangler_new::mangleRef( const ast::BaseInstType * refType, std::string prefix ) {
 			printQualifiers( refType );
 
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ src/SymTab/Validate.cc	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -960,4 +960,16 @@
 	}
 
+	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
@@ -968,11 +980,9 @@
 			ret->location = typeInst->location;
 			ret->get_qualifiers() |= typeInst->get_qualifiers();
-			// attributes are not carried over from typedef to function parameters/return values
-			if ( ! inFunctionType ) {
-				ret->attributes.splice( ret->attributes.end(), typeInst->attributes );
-			} else {
-				deleteAll( ret->attributes );
-				ret->attributes.clear();
-			}
+			// 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() ) {
@@ -1508,5 +1518,5 @@
 		}
 
-		void checkGenericParameters( const ast::ReferenceToType * inst ) {
+		void checkGenericParameters( const ast::BaseInstType * inst ) {
 			for ( const ast::Expr * param : inst->params ) {
 				if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) {
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ tests/Makefile.am	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -38,4 +38,6 @@
 # since automake doesn't have support for CFA we have to
 AM_CFLAGS = $(if $(test), 2> $(test), ) \
+	-fdebug-prefix-map=$(abspath ${abs_srcdir})= \
+	-fdebug-prefix-map=/tmp= \
 	-g \
 	-Wall \
@@ -110,5 +112,5 @@
 % : %.cfa $(CFACCBIN)
 	$(CFACOMPILETEST) -c -o $(abspath ${@}).o
-	$(CFACCLOCAL) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) $(abspath ${@}).o -o $(abspath ${@})
+	$(CFACCLOCAL) $(if $(test), 2> $(test), ) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) ${@}.o -o $(abspath ${@})
 
 # implicit rule for c++ test
@@ -137,4 +139,8 @@
 # CUSTOM TARGET
 #------------------------------------------------------------------------------
+# tests that just validate syntax
+expression : expression.cfa $(CFACCBIN)
+	$(CFACOMPILETEST) -c -fsyntax-only 2> $(abspath ${@})
+
 # expected failures
 # use custom target since they require a custom define and custom dependencies
Index: tests/concurrent/.expect/join.txt
===================================================================
--- tests/concurrent/.expect/join.txt	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
+++ tests/concurrent/.expect/join.txt	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -0,0 +1,2 @@
+All workers got 42
+All other workers got 27
Index: tests/concurrent/join.cfa
===================================================================
--- tests/concurrent/join.cfa	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
+++ tests/concurrent/join.cfa	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -0,0 +1,52 @@
+#include <fstream.hfa>
+#include <thread.hfa>
+
+thread Worker { volatile int result; };
+
+void main(Worker & this) {
+	this.result = -10;
+	for(50) {
+		yield();
+	}
+	this.result = 42;
+}
+
+thread OtherWorker { volatile int result; };
+
+void main(OtherWorker & this) {
+	this.result = -10;
+	LOOP: for() {
+		waitfor( ^?{} : this) {
+			break LOOP;
+		}
+		or else {
+			yield();
+		}
+	}
+	this.result = 27;
+}
+
+
+int main(int argc, char* argv[]) {
+	{
+		Worker workers[17];
+		for(i; 17) {
+			int res = join( workers[i] ).result;
+			if( res != 42 ) {
+				sout | "Worker" | i | "got incorrect result:" | res;
+			}
+		}
+	}
+	sout | "All workers got 42";
+
+	{
+		OtherWorker workers[17];
+		for(i; 17) {
+			int res = join( workers[i] ).result;
+			if( res != 27 ) {
+				sout | "Other Worker" | i | "got incorrect result:" | res;
+			}
+		}
+	}
+	sout | "All other workers got 27";
+}
Index: tests/concurrent/joinerror.cfa
===================================================================
--- tests/concurrent/joinerror.cfa	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
+++ tests/concurrent/joinerror.cfa	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -0,0 +1,61 @@
+#include <fstream.hfa>
+#include <thread.hfa>
+
+thread Worker { volatile int result; };
+
+void main(Worker & this) {
+	this.result = -10;
+	for(50) {
+		yield();
+	}
+	this.result = 42;
+}
+
+int get_result( Worker & mutex this ) {
+	return this.result;
+}
+
+thread OtherWorker { volatile int result; };
+
+void main(OtherWorker & this) {
+	this.result = -10;
+	LOOP: for() {
+		waitfor( ^?{} : this) {
+			break LOOP;
+		}
+		or else {
+			yield();
+		}
+	}
+	this.result = 27;
+}
+
+int get_result( OtherWorker & mutex this ) {
+	return this.result;
+}
+
+int main(int argc, char* argv[]) {
+	{
+		Worker workers[17];
+		for(i; 17) {
+			join( workers[i] );
+			int res = get_result( workers[i] );
+			if( res != 42 ) {
+				sout | "Worker" | i | "got incorrect result:" | res;
+			}
+		}
+	}
+	sout | "All workers got 42";
+
+	{
+		OtherWorker workers[17];
+		for(i; 17) {
+			join( workers[i] );
+			int res = get_result( workers[i] );
+			if( res != 27 ) {
+				sout | "Other Worker" | i | "got incorrect result:" | res;
+			}
+		}
+	}
+	sout | "All other workers got 27";
+}
Index: tests/linking/.expect/linkerror.txt
===================================================================
--- tests/linking/.expect/linkerror.txt	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
+++ tests/linking/.expect/linkerror.txt	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -0,0 +1,4 @@
+CFA Version 1.0.0 (debug)
+linking/linkerror.o: In function `_X4mainFi___1':
+linking/linkerror.cfa:6: undefined reference to `_X18this_doesnot_existFv_i__1'
+collect2: error: ld returned 1 exit status
Index: tests/linking/linkerror.cfa
===================================================================
--- tests/linking/linkerror.cfa	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
+++ tests/linking/linkerror.cfa	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -0,0 +1,7 @@
+// This is more of a meta test, to confirm the test suite handles link errors correctly.
+
+extern void this_doesnot_exist(int);
+
+int main() {
+	this_doesnot_exist( 6 );
+}
Index: tests/pybin/tools.py
===================================================================
--- tests/pybin/tools.py	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ tests/pybin/tools.py	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -120,5 +120,5 @@
 		return None
 
-	file = open(file, mode)
+	file = open(file, mode, encoding="latin-1") # use latin-1 so all chars mean something.
 	exitstack.push(file)
 	return file
Index: tests/test.py
===================================================================
--- tests/test.py	(revision c402739f790c375d9b5414d824619c6457f1948d)
+++ tests/test.py	(revision 2724b4e7228c1f0319a3f48ac1d5b1ffefa4421d)
@@ -207,5 +207,5 @@
 		else:
 			if os.stat(out_file).st_size < 1048576:
-				with open (out_file, "r") as myfile:
+				with open (out_file, "r", encoding='latin-1') as myfile:  # use latin-1 so all chars mean something.
 					error = myfile.read()
 			else:
