Index: doc/bibliography/pl.bib
===================================================================
--- doc/bibliography/pl.bib	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/bibliography/pl.bib	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -1439,10 +1439,10 @@
     contributer	= {pabuhr@plg},
     author	= {Peter A. Buhr},
-    title	= {$\mu${C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Annotated Reference Manual, Version 6.1.0},
+    title	= {$\mu${C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Annotated Reference Manual, Version 7.0.0},
     institution	= {School of Computer Science, University of Waterloo},
     address	= {Waterloo, Ontario, Canada, N2L 3G1},
-    month	= jul,
-    year	= 2015,
-    note	= {\href{http://plg.uwaterloo.ca/~usystem/pub/uSystem/u++-6.1.0.sh}{http://\-plg.\-uwaterloo.\-ca/\-$\sim$usystem/\-pub/\-uSystem/\-u++-6.1.0.sh}},
+    month	= dec,
+    year	= 2017,
+    note	= {\href{http://plg.uwaterloo.ca/~usystem/pub/uSystem/u++-7.0.0.sh}{http://\-plg.\-uwaterloo.\-ca/\-$\sim$usystem/\-pub/\-uSystem/\-u++-7.0.0.sh}},
 }
 
Index: doc/papers/general/Paper.tex
===================================================================
--- doc/papers/general/Paper.tex	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/Paper.tex	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -58,4 +58,5 @@
 \setlength{\parindentlnth}{\parindent}
 
+\newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{\lst@basicstyle{#1}}}}
 \newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}}
 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
@@ -231,4 +232,8 @@
 All of the features discussed in this paper are working, unless a feature states it is a future feature for completion.
 
+Finally, it is impossible to describe a programming language without usages before definitions.
+Therefore, syntax and semantics appear before explanations;
+hence, patience is necessary until details are presented.
+
 
 \section{Polymorphic Functions}
@@ -263,13 +268,15 @@
 \end{cfa}
 \CFA maximizes the ability to reuse names to aggressively address the naming problem.
-In some cases, hundreds of names can be reduced to tens, resulting in a significant cognitive reduction for a programmer.
+In some cases, hundreds of names can be reduced to tens, resulting in a significant cognitive reduction.
 In the above, the name @max@ has a consistent meaning, and a programmer only needs to remember the single concept: maximum.
 To prevent significant ambiguities, \CFA uses the return type in selecting overloads, \eg in the assignment to @m@, the compiler use @m@'s type to unambiguously select the most appropriate call to function @max@ (as does Ada).
 As is shown later, there are a number of situations where \CFA takes advantage of available type information to disambiguate, where other programming languages generate ambiguities.
 
-\Celeven added @_Generic@ expressions, which can be used in preprocessor macros to provide a form of ad-hoc polymorphism; however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading. 
-The macro wrapping the generic expression imposes some limitations; as an example, it could not implement the example above, because the variables @max@ would collide with the functions @max@. 
-Ergonomic limitations of @_Generic@ include the necessity to put a fixed list of supported types in a single place and manually dispatch to appropriate overloads, as well as possible namespace pollution from the functions dispatched to, which must all have distinct names.
-Though name-overloading removes a major use-case for @_Generic@ expressions, \CFA implements @_Generic@ for backwards-compatibility purposes. \TODO{actually implement that}
+\Celeven added @_Generic@ expressions, which is used in preprocessor macros to provide a form of ad-hoc polymorphism;
+however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading. 
+The macro wrapping the generic expression imposes some limitations;
+\eg, it cannot implement the example above, because the variables @max@ are ambiguous with the functions @max@. 
+Ergonomic limitations of @_Generic@ include the necessity to put a fixed list of supported types in a single place and manually dispatch to appropriate overloads, as well as possible namespace pollution from the dispatch functions, which must all have distinct names.
+For backwards compatibility, \CFA supports @_Generic@ expressions, but it is an unnecessary mechanism. \TODO{actually implement that}
 
 % http://fanf.livejournal.com/144696.html
@@ -286,10 +293,10 @@
 int forty_two = identity( 42 );				$\C{// T is bound to int, forty\_two == 42}$
 \end{cfa}
-The @identity@ function above can be applied to any complete \newterm{object type} (or @otype@).
+This @identity@ function can be applied to any complete \newterm{object type} (or @otype@).
 The type variable @T@ is transformed into a set of additional implicit parameters encoding sufficient information about @T@ to create and return a variable of that type.
 The \CFA implementation passes the size and alignment of the type represented by an @otype@ parameter, as well as an assignment operator, constructor, copy constructor and destructor.
 If this extra information is not needed, \eg for a pointer, the type parameter can be declared as a \newterm{data type} (or @dtype@).
 
-In \CFA, the polymorphism runtime-cost is spread over each polymorphic call, due to passing more arguments to polymorphic functions;
+In \CFA, the polymorphic runtime-cost is spread over each polymorphic call, because more arguments are passed to polymorphic functions;
 the experiments in Section~\ref{sec:eval} show this overhead is similar to \CC virtual-function calls.
 A design advantage is that, unlike \CC template-functions, \CFA polymorphic-functions are compatible with C \emph{separate compilation}, preventing compilation and code bloat.
@@ -303,5 +310,5 @@
 which works for any type @T@ with a matching addition operator.
 The polymorphism is achieved by creating a wrapper function for calling @+@ with @T@ bound to @double@, then passing this function to the first call of @twice@.
-There is now the option of using the same @twice@ and converting the result to @int@ on assignment, or creating another @twice@ with type parameter @T@ bound to @int@ because \CFA uses the return type~\cite{Cormack81,Baker82,Ada}, in its type analysis.
+There is now the option of using the same @twice@ and converting the result to @int@ on assignment, or creating another @twice@ with type parameter @T@ bound to @int@ because \CFA uses the return type~\cite{Cormack81,Baker82,Ada} in its type analysis.
 The first approach has a late conversion from @double@ to @int@ on the final assignment, while the second has an eager conversion to @int@.
 \CFA minimizes the number of conversions and their potential to lose information, so it selects the first approach, which corresponds with C-programmer intuition.
@@ -312,9 +319,8 @@
 \begin{cfa}
 void * bsearch( const void * key, const void * base, size_t nmemb, size_t size,
-				int (* compar)( const void *, const void * ));
-
-int comp( const void * t1, const void * t2 ) { return *(double *)t1 < *(double *)t2 ? -1 :
-				*(double *)t2 < *(double *)t1 ? 1 : 0; }
-
+					 int (* compar)( const void *, const void * ));
+int comp( const void * t1, const void * t2 ) {
+	 return *(double *)t1 < *(double *)t2 ? -1 : *(double *)t2 < *(double *)t1 ? 1 : 0;
+}
 double key = 5.0, vals[10] = { /* 10 sorted float values */ };
 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp );	$\C{// search sorted array}$
@@ -324,10 +330,10 @@
 forall( otype T | { int ?<?( T, T ); } ) T * bsearch( T key, const T * arr, size_t size ) {
 	int comp( const void * t1, const void * t2 ) { /* as above with double changed to T */ }
-	return (T *)bsearch( &key, arr, size, sizeof(T), comp ); }
-
+	return (T *)bsearch( &key, arr, size, sizeof(T), comp );
+}
 forall( otype T | { int ?<?( T, T ); } ) unsigned int bsearch( T key, const T * arr, size_t size ) {
 	T * result = bsearch( key, arr, size );	$\C{// call first version}$
-	return result ? result - arr : size; }	$\C{// pointer subtraction includes sizeof(T)}$
-
+	return result ? result - arr : size;	$\C{// pointer subtraction includes sizeof(T)}$
+}
 double * val = bsearch( 5.0, vals, 10 );	$\C{// selection based on return type}$
 int posn = bsearch( 5.0, vals, 10 );
@@ -336,5 +342,5 @@
 Providing a hidden @comp@ function in \CC is awkward as lambdas do not use C calling-conventions and template declarations cannot appear at block scope.
 As well, an alternate kind of return is made available: position versus pointer to found element.
-\CC's type-system cannot disambiguate between the two versions of @bsearch@ because it does not use the return type in overload resolution, nor can \CC separately compile a templated @bsearch@.
+\CC's type-system cannot disambiguate between the two versions of @bsearch@ because it does not use the return type in overload resolution, nor can \CC separately compile a template @bsearch@.
 
 \CFA has replacement libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions, all without rewriting the actual computations (see Section~\ref{sec:libraries}).
@@ -382,8 +388,8 @@
 \begin{cfa}
 trait otype( dtype T | sized(T) ) {  // sized is a pseudo-trait for types with known size and alignment
-	void ?{}( T * );						$\C{// default constructor}$
-	void ?{}( T *, T );						$\C{// copy constructor}$
-	void ?=?( T *, T );						$\C{// assignment operator}$
-	void ^?{}( T * ); };					$\C{// destructor}$
+	void ?{}( T & );						$\C{// default constructor}$
+	void ?{}( T &, T );						$\C{// copy constructor}$
+	void ?=?( T &, T );						$\C{// assignment operator}$
+	void ^?{}( T & ); };					$\C{// destructor}$
 \end{cfa}
 Given the information provided for an @otype@, variables of polymorphic type can be treated as if they were a complete type: stack-allocatable, default or copy-initialized, assigned, and deleted.
@@ -429,8 +435,8 @@
 One approach is to write bespoke data-structures for each context in which they are needed.
 While this approach is flexible and supports integration with the C type-checker and tooling, it is also tedious and error-prone, especially for more complex data structures.
-A second approach is to use @void *@--based polymorphism, \eg the C standard-library functions @bsearch@ and @qsort@, which allows reuse of code with common functionality.
+A second approach is to use @void *@--based polymorphism, \eg the C standard-library functions @bsearch@ and @qsort@, which allow reuse of code with common functionality.
 However, basing all polymorphism on @void *@ eliminates the type-checker's ability to ensure that argument types are properly matched, often requiring a number of extra function parameters, pointer indirection, and dynamic allocation that is not otherwise needed.
 A third approach to generic code is to use preprocessor macros, which does allow the generated code to be both generic and type-checked, but errors may be difficult to interpret.
-Furthermore, writing and using preprocessor macros can be unnatural and inflexible.
+Furthermore, writing and using preprocessor macros is unnatural and inflexible.
 
 \CC, Java, and other languages use \newterm{generic types} to produce type-safe abstract data-types.
@@ -444,13 +450,13 @@
 	S second;
 };
-forall( otype T ) T value( pair( const char *, T ) p ) { return p.second; }
-forall( dtype F, otype T ) T value( pair( F *, T * ) p ) { return *p.second; }
-
-pair( const char *, int ) p = { "magic", 42 };
+forall( otype T ) T value( pair( const char *, T ) p ) { return p.second; } $\C{// dynamic}$
+forall( dtype F, otype T ) T value( pair( F *, T * ) p ) { return *p.second; } $\C{// dtype-static (concrete)}$
+
+pair( const char *, int ) p = { "magic", 42 }; $\C{// concrete}$
 int i = value( p );
-pair( void *, int * ) q = { 0, &p.second };
+pair( void *, int * ) q = { 0, &p.second }; $\C{// concrete}$
 i = value( q );
 double d = 1.0;
-pair( double *, double * ) r = { &d, &d };
+pair( double *, double * ) r = { &d, &d }; $\C{// concrete}$
 d = value( r );
 \end{cfa}
@@ -458,5 +464,5 @@
 \CFA classifies generic types as either \newterm{concrete} or \newterm{dynamic}.
 Concrete types have a fixed memory layout regardless of type parameters, while dynamic types vary in memory layout depending on their type parameters.
-A type may have polymorphic parameters but still be concrete, called \newterm{dtype-static}.
+A \newterm{dtype-static} type has polymorphic parameters but is still concrete.
 Polymorphic pointers are an example of dtype-static types, \eg @forall(dtype T) T *@ is a polymorphic type, but for any @T@, @T *@  is a fixed-sized pointer, and therefore, can be represented by a @void *@ in code generation.
 
@@ -475,5 +481,5 @@
 For example, the concrete instantiation for @pair( const char *, int )@ is:
 \begin{cfa}
-struct _pair_conc1 {
+struct _pair_conc0 {
 	const char * first;
 	int second;
@@ -482,7 +488,7 @@
 
 A concrete generic-type with dtype-static parameters is also expanded to a structure type, but this type is used for all matching instantiations.
-In the above example, the @pair( F *, T * )@ parameter to @value_p@ is such a type; its expansion is below and it is used as the type of the variables @q@ and @r@ as well, with casts for member access where appropriate:
-\begin{cfa}
-struct _pair_conc0 {
+In the above example, the @pair( F *, T * )@ parameter to @value@ is such a type; its expansion is below and it is used as the type of the variables @q@ and @r@ as well, with casts for member access where appropriate:
+\begin{cfa}
+struct _pair_conc1 {
 	void * first;
 	void * second;
@@ -496,5 +502,5 @@
 As mentioned in Section~\ref{sec:poly-fns}, @otype@ function parameters (in fact all @sized@ polymorphic parameters) come with implicit size and alignment parameters provided by the caller.
 Dynamic generic-types also have an \newterm{offset array} containing structure-member offsets.
-A dynamic generic-union needs no such offset array, as all members are at offset 0, but size and alignment are still necessary.
+A dynamic generic-@union@ needs no such offset array, as all members are at offset 0, but size and alignment are still necessary.
 Access to members of a dynamic structure is provided at runtime via base-displacement addressing with the structure pointer and the member offset (similar to the @offsetof@ macro), moving a compile-time offset calculation to runtime.
 
@@ -502,6 +508,13 @@
 If a dynamic generic-type is declared to be passed or returned by value from a polymorphic function, the translator can safely assume the generic type is complete (\ie has a known layout) at any call-site, and the offset array is passed from the caller;
 if the generic type is concrete at the call site, the elements of this offset array can even be statically generated using the C @offsetof@ macro.
-As an example, @p.second@ in the @value@ function above is implemented as @*(p + _offsetof_pair[1])@, where @p@ is a @void *@, and @_offsetof_pair@ is the offset array passed into @value@ for @pair( const char *, T )@.
-The offset array @_offsetof_pair@ is generated at the call site as @size_t _offsetof_pair[] = { offsetof(_pair_conc1, first), offsetof(_pair_conc1, second) }@.
+As an example, the body of the second @value@ function is implemented like this:
+\begin{cfa}
+_assign_T(_retval, p + _offsetof_pair[1]); $\C{// return *p.second}$
+\end{cfa}
+@_assign_T@ is passed in as an implicit parameter from @otype T@, and takes two @T*@ (@void*@ in the generated code), a destination and a source; @_retval@ is the pointer to a caller-allocated buffer for the return value, the usual \CFA method to handle dynamically-sized return types.
+@_offsetof_pair@ is the offset array passed into @value@; this array is generated at the call site as:
+\begin{cfa}
+size_t _offsetof_pair[] = { offsetof(_pair_conc0, first), offsetof(_pair_conc0, second) }
+\end{cfa}
 
 In some cases the offset arrays cannot be statically generated.
@@ -586,5 +599,5 @@
 \subsection{Tuple Expressions}
 
-The addition of multiple-return-value functions (MRVF) are useless without a syntax for accepting multiple values at the call-site.
+The addition of multiple-return-value functions (MRVF) are \emph{useless} without a syntax for accepting multiple values at the call-site.
 The simplest mechanism for capturing the return values is variable assignment, allowing the values to be retrieved directly.
 As such, \CFA allows assigning multiple values from a function into multiple variables, using a square-bracketed list of lvalue expressions (as above), called a \newterm{tuple}.
@@ -817,10 +830,10 @@
 Hence, function parameter and return lists are flattened for the purposes of type unification allowing the example to pass expression resolution.
 This relaxation is possible by extending the thunk scheme described by Bilson~\cite{Bilson03}.
-Whenever a candidate's parameter structure does not exactly match the formal parameter's structure, a thunk is generated to specialize calls to the actual function:
-\begin{cfa}
-int _thunk( int _p0, double _p1, double _p2 ) { return f( [_p0, _p1], _p2 ); }
-\end{cfa}
-so the thunk provides flattening and structuring conversions to inferred functions, improving the compatibility of tuples and polymorphism.
-These thunks take advantage of gcc C nested-functions to produce closures that have the usual function-pointer signature.
+% Whenever a candidate's parameter structure does not exactly match the formal parameter's structure, a thunk is generated to specialize calls to the actual function:
+% \begin{cfa}
+% int _thunk( int _p0, double _p1, double _p2 ) { return f( [_p0, _p1], _p2 ); }
+% \end{cfa}
+% so the thunk provides flattening and structuring conversions to inferred functions, improving the compatibility of tuples and polymorphism.
+% These thunks are generated locally using gcc nested-functions, rather hositing them to the external scope, so they can easily access local state.
 
 
@@ -878,5 +891,5 @@
 	print(arg);  print(rest);
 }
-void print( char * x ) { printf( "%s", x ); }
+void print( const char * x ) { printf( "%s", x ); }
 void print( int x ) { printf( "%d", x ); }
 void print( S s ) { print( "{ ", s.x, ",", s.y, " }" ); }
@@ -887,4 +900,5 @@
 The polymorphic @print@ allows printing any list of types, where as each individual type has a @print@ function.
 The individual print functions can be used to build up more complicated @print@ functions, such as @S@, which cannot be done with @printf@ in C.
+This mechanism is used to seamlessly print tuples in the \CFA I/O library (see Section~\ref{s:IOLibrary}).
 
 Finally, it is possible to use @ttype@ polymorphism to provide arbitrary argument forwarding functions.
@@ -990,5 +1004,5 @@
 \section{Control Structures}
 
-\CFA identifies inconsistent, problematic, and missing control structures in C, and extends, modifies, and adds to control structures to increase functionality and safety.
+\CFA identifies inconsistent, problematic, and missing control structures in C, and extends, modifies, and adds control structures to increase functionality and safety.
 
 
@@ -1025,5 +1039,5 @@
 \lstMakeShortInline@%
 \end{cquote}
-for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.}
+for a contiguous list:\footnote{gcc has the same mechanism but awkward syntax, \lstinline@2 ...42@, because a space is required after a number, otherwise the period is a decimal point.}
 \begin{cquote}
 \lstDeleteShortInline@%
@@ -1078,4 +1092,5 @@
 While the ability to fall through \emph{is} a useful form of control flow, it does not match well with programmer intuition, resulting in many errors from missing @break@ statements.
 For backwards compatibility, \CFA provides a \emph{new} control structure, @choose@, which mimics @switch@, but reverses the meaning of fall through (see Figure~\ref{f:ChooseSwitchStatements}).
+
 Collectively, these enhancements reduce programmer burden and increase readability and safety.
 
@@ -1237,5 +1252,5 @@
 \end{figure}
 
-Both labelled @continue@ and @break@ are a @goto@ restricted in the following ways:
+With respect to safety, both labelled @continue@ and @break@ are a @goto@ restricted in the following ways:
 \begin{itemize}
 \item
@@ -1250,11 +1265,11 @@
 With @goto@, the label is at the end of the control structure, which fails to convey this important clue early enough to the reader.
 Finally, using an explicit target for the transfer instead of an implicit target allows new constructs to be added or removed without affecting existing constructs.
-The implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed.
+Otherwise, the implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed.
 
 
 \subsection{Exception Handling}
 
-The following framework for \CFA exception handling is in place, excluding a run-time type information and dynamic casts.
-\CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling}).
+The following framework for \CFA exception handling is in place, excluding some run-time type-information and dynamic casts.
+\CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling})~\cite{Buhr92b,Buhr00a}.
 Both mechanisms provide dynamic call to a handler using dynamic name-lookup, where fix-up has dynamic return and recovery has static return from the handler.
 \CFA restricts exception types to those defined by aggregate type @exception@.
@@ -1333,5 +1348,5 @@
 resume( $\emph{alternate-stack}$ )
 \end{cfa}
-These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another coroutine or task~\cite{Delisle18}.
+These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another \CFA coroutine or task~\cite{Delisle18}.\footnote{\CFA coroutine and concurrency features are discussed in a separately submitted paper.}
 Nonlocal raise is restricted to resumption to provide the exception handler the greatest flexibility because processing the exception does not unwind its stack, allowing it to continue after the handle returns.
 
@@ -1358,4 +1373,16 @@
 Specifying no exception type is shorthand for specifying all exception types.
 Both @enable@ and @disable@ blocks can be nested, turning propagation on/off on entry, and on exit, the specified exception types are restored to their prior state.
+Coroutines and tasks start with non-local exceptions disabled, allowing handlers to be put in place, before non-local exceptions are explicitly enabled.
+\begin{cfa}
+void main( mytask & c ) {					$\C{// thread starts here}$
+	// non-local exceptions disabled
+	try {									$\C{// establish handles for non-local exceptions}$
+		enable {							$\C{// allow non-local exception delivery}$
+			// task body
+		}
+	// appropriate catchResume/catch handlers
+	}
+}
+\end{cfa}
 
 Finally, \CFA provides a Java like  @finally@ clause after the catch clauses:
@@ -1461,5 +1488,5 @@
 Qualification or a cast is used to disambiguate.
 
-There is an interesting problem between parameters and the function @with@, \eg:
+There is an interesting problem between parameters and the function-body @with@, \eg:
 \begin{cfa}
 void ?{}( S & s, int i ) with ( s ) {		$\C{// constructor}$
@@ -1467,5 +1494,5 @@
 }
 \end{cfa}
-Here, the assignment @s.i = i@ means @s.i = s.i@, which is meaningless, and there is no mechanism to qualify the parameter @i@, making the assignment impossible using the function @with@.
+Here, the assignment @s.i = i@ means @s.i = s.i@, which is meaningless, and there is no mechanism to qualify the parameter @i@, making the assignment impossible using the function-body @with@.
 To solve this problem, parameters are treated like an initialized aggregate:
 \begin{cfa}
@@ -1475,8 +1502,8 @@
 } params;
 \end{cfa}
-and implicitly opened \emph{after} a function open, to give them higher priority:
-\begin{cfa}
-void ?{}( S & s, int i ) with ( s ) `with( $\emph{\color{red}params}$ )` {
-	s.i = i; j = 3; m = 5.5;
+and implicitly opened \emph{after} a function-body open, to give them higher priority:
+\begin{cfa}
+void ?{}( S & s, int `i` ) with ( s ) `with( $\emph{\color{red}params}$ )` {
+	s.i = `i`; j = 3; m = 5.5;
 }
 \end{cfa}
@@ -1539,5 +1566,5 @@
 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice.
 
-\CFA provides its own type, variable and function declarations, using a different syntax.
+\CFA provides its own type, variable and function declarations, using a different syntax~\cite[pp.~856--859]{Buhr94a}.
 The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right.
 The qualifiers have the same meaning but are ordered left to right to specify a variable's type.
@@ -1774,5 +1801,5 @@
 int & r = *new( int );
 ...											$\C{// non-null reference}$
-delete &r;
+delete &r;									$\C{// unmanaged (programmer) memory-management}$
 r += 1;										$\C{// undefined reference}$
 \end{cfa}
@@ -1921,7 +1948,7 @@
 Constructor calls seamlessly integrate with existing C initialization syntax, providing a simple and familiar syntax to C programmers and allowing constructor calls to be inserted into legacy C code with minimal code changes.
 
-In \CFA, a constructor is named @?{}@ and a destructor is named @^?{}@.
-The name @{}@ comes from the syntax for the initializer: @struct S { int i, j; } s = `{` 2, 3 `}`@\footnote{%
+In \CFA, a constructor is named @?{}@ and a destructor is named @^?{}@\footnote{%
 The symbol \lstinline+^+ is used for the destructor name because it was the last binary operator that could be used in a unary context.}.
+The name @{}@ comes from the syntax for the initializer: @struct S { int i, j; } s = `{` 2, 3 `}`@.
 Like other \CFA operators, these names represent the syntax used to call the constructor or destructor, \eg @?{}(x, ...)@ or @^{}(x, ...)@.
 The constructor and destructor have return type @void@, and the first parameter is a reference to the object type to be constructed or destructed.
@@ -1951,5 +1978,5 @@
 }
 \end{cfa}
-(Note, the example is purposely kept simple by using shallow-copy semantics.)
+(Note, the example is purposely simplified using shallow-copy semantics.)
 An initialization constructor-call has the same syntax as a C initializer, except the initialization values are passed as arguments to a matching constructor (number and type of paremeters).
 \begin{cfa}
@@ -2004,5 +2031,7 @@
 C already includes limited polymorphism for literals -- @0@ can be either an integer or a pointer literal, depending on context, while the syntactic forms of literals of the various integer and float types are very similar, differing from each other only in suffix.
 In keeping with the general \CFA approach of adding features while respecting the ``C-style'' of doing things, C's polymorphic constants and typed literal syntax are extended to interoperate with user-defined types, while maintaining a backwards-compatible semantics.
-A trivial example is allowing the underscore, as in Ada, to separate prefixes, digits, and suffixes in all \CFA constants, \eg @0x`_`1.ffff`_`ffff`_`p`_`128`_`l@.
+
+A simple example is allowing the underscore, as in Ada, to separate prefixes, digits, and suffixes in all \CFA constants, \eg @0x`_`1.ffff`_`ffff`_`p`_`128`_`l@, where the underscore is also the standard separator in C identifiers.
+\CC uses a single quote as a separator but it is restricted among digits, precluding its use in the literal prefix or suffix, \eg @0x1.ffff@@`'@@ffffp128l@, and causes problems with most IDEs, which must be extended to deal with this alternate use of the single quote.
 
 
@@ -2014,25 +2043,25 @@
 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
 \begin{cfa}
-20`_hh`     // signed char
-21`_hhu`   // unsigned char
-22`_h`       // signed short int
-23`_uh`     // unsigned short int
-24`z`         // size_t
-\end{cfa}
-&
-\begin{cfa}
-20`_L8`      // int8_t
-21`_ul8`     // uint8_t
-22`_l16`     // int16_t
-23`_ul16`   // uint16_t
-24`_l32`     // int32_t
-\end{cfa}
-&
-\begin{cfa}
-25`_ul32`      // uint32_t
-26`_l64`        // int64_t
-27`_l64u`      // uint64_t
-26`_L128`     // int128
-27`_L128u`   // unsigned int128
+20_`hh`     // signed char
+21_`hhu`   // unsigned char
+22_`h`       // signed short int
+23_`uh`     // unsigned short int
+24_`z`       // size_t
+\end{cfa}
+&
+\begin{cfa}
+20_`L8`      // int8_t
+21_`ul8`     // uint8_t
+22_`l16`     // int16_t
+23_`ul16`   // uint16_t
+24_`l32`     // int32_t
+\end{cfa}
+&
+\begin{cfa}
+25_`ul32`      // uint32_t
+26_`l64`        // int64_t
+27_`l64u`      // uint64_t
+26_`L128`     // int128
+27_`L128u`   // unsigned int128
 \end{cfa}
 \end{tabular}
@@ -2043,14 +2072,21 @@
 \subsection{0/1}
 
-In C, @0@ has the special property that it is the only ``false'' value; by the standard, any value which compares equal to @0@ is false, while any value that compares unequal to @0@ is true. 
-As such, an expression @x@ in any boolean context (such as the condition of an @if@ or @while@ statement, or the arguments to @&&@, @||@, or @?:@) can be rewritten as @x != 0@ without changing its semantics.
-The operator overloading feature of \CFA provides a natural means to implement this truth value comparison for arbitrary types, but the C type system is not precise enough to distinguish an equality comparison with @0@ from an equality comparison with an arbitrary integer or pointer. 
-To provide this precision, \CFA introduces a new type @zero_t@ as type type of literal @0@ (somewhat analagous to @nullptr_t@ and @nullptr@ in \CCeleven); @zero_t@ can only take the value @0@, but has implicit conversions to the integer and pointer types so that C code involving @0@ continues to work properly. 
-With this addition, the \CFA compiler rewrites @if (x)@ and similar expressions to @if ((x) != 0)@ or the appropriate analogue, and any type @T@ can be made ``truthy'' by defining an operator overload @int ?!=?(T, zero_t)@.
-\CC makes types truthy by adding a conversion to @bool@; prior to the addition of explicit cast operators in \CCeleven this approach had the pitfall of making truthy types transitively convertable to any numeric type; our design for \CFA avoids this issue.
-
-\CFA also includes a special type for @1@, @one_t@; like @zero_t@, @one_t@ has built-in implicit conversions to the various integral types so that @1@ maintains its expected semantics in legacy code. 
-The addition of @one_t@ allows generic algorithms to handle the unit value uniformly for types where that is meaningful. 
-\TODO{Make this sentence true} In particular, polymorphic functions in the \CFA prelude define @++x@ and @x++@ in terms of @x += 1@, allowing users to idiomatically define all forms of increment for a type @T@ by defining the single function @T & ?+=(T &, one_t)@; analogous overloads for the decrement operators are present as well.
+In C, @0@ has the special property that it is the only ``false'' value;
+from the standard, any value that compares equal to @0@ is false, while any value that compares unequal to @0@ is true. 
+As such, an expression @x@ in any boolean context (such as the condition of an @if@ or @while@ statement, or the arguments to @&&@, @||@, or @?:@\,) can be rewritten as @x != 0@ without changing its semantics.
+Operator overloading in \CFA provides a natural means to implement this truth-value comparison for arbitrary types, but the C type system is not precise enough to distinguish an equality comparison with @0@ from an equality comparison with an arbitrary integer or pointer. 
+To provide this precision, \CFA introduces a new type @zero_t@ as the type of literal @0@ (somewhat analagous to @nullptr_t@ and @nullptr@ in \CCeleven);
+@zero_t@ can only take the value @0@, but has implicit conversions to the integer and pointer types so that C code involving @0@ continues to work. 
+With this addition, \CFA rewrites @if (x)@ and similar expressions to @if ((x) != 0)@ or the appropriate analogue, and any type @T@ is ``truthy'' by defining an operator overload @int ?!=?(T, zero_t)@.
+\CC makes types truthy by adding a conversion to @bool@;
+prior to the addition of explicit cast operators in \CCeleven, this approach had the pitfall of making truthy types transitively convertable to any numeric type;
+\CFA avoids this issue.
+
+Similarly, \CFA also has a special type for @1@, @one_t@;
+like @zero_t@, @one_t@ has built-in implicit conversions to the various integral types so that @1@ maintains its expected semantics in legacy code for operations @++@ and @--@.
+The addition of @one_t@ allows generic algorithms to handle the unit value uniformly for types where it is meaningful.
+\TODO{Make this sentence true}
+In particular, polymorphic functions in the \CFA prelude define @++x@ and @x++@ in terms of @x += 1@, allowing users to idiomatically define all forms of increment for a type @T@ by defining the single function @T & ?+=(T &, one_t)@;
+analogous overloads for the decrement operators are present as well.
 
 
@@ -2060,5 +2096,5 @@
 The left of Figure~\ref{f:UserLiteral} shows the \CFA alternative call-syntax (literal argument before function name), using the backquote, to convert basic literals into user literals.
 The backquote is a small character, making the unit (function name) predominate.
-For examples, the multi-precision integers in Section~\ref{s:MultiPrecisionIntegers} make use of user literals:
+For examples, the multi-precision integer-type in Section~\ref{s:MultiPrecisionIntegers} has user literals:
 {\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}}
 \begin{cfa}
@@ -2073,5 +2109,4 @@
 After which, user literals must match (no conversions);
 hence, it is necessary to overload the unit with all appropriate types.
-Finally, the use of the single quote as a separator is restricted to digits, precluding its use in the literal prefix or suffix, and causes problems with most IDEs, which must be extended to deal with this alternate use of the single quote.
 
 \begin{figure}
@@ -2125,5 +2160,5 @@
 	w = 155|_lb|;
 	w = 0b1111|_lb|;       // error, binary unsupported
-	w = 0${\color{red}'}$233|_lb|;          // quote separator
+	w = 0${\color{red}\LstBasicStyle{'}}$233|_lb|;          // quote separator
 	w = 0x9b|_kg|;
 	w = 5.5d|_st| + 8|_kg| + 25.01|_lb| + heavy;
@@ -2281,5 +2316,5 @@
 \lstMakeShortInline@%
 \end{cquote}
-In additon, there are polymorphic functions, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@.
+In additon, there are polymorphic functions, like @min@ and @max@, that work on any type with operators @?<?@ or @?>?@.
 
 The following shows one example where \CFA \emph{extends} an existing standard C interface to reduce complexity and provide safety.
@@ -2287,18 +2322,18 @@
 \begin{description}[topsep=3pt,itemsep=2pt,parsep=0pt]
 \item[fill]
-after allocation the storage is filled with a specified character.
+an allocation with a specified character.
 \item[resize]
-an existing allocation is decreased or increased in size.
+an existing allocation to decreased or increased its size.
 In either case, new storage may or may not be allocated and, if there is a new allocation, as much data from the existing allocation is copied.
 For an increase in storage size, new storage after the copied data may be filled.
-\item[alignment]
-an allocation starts on a specified memory boundary, \eg, an address multiple of 64 or 128 for cache-line purposes.
+\item[align]
+an allocation on a specified memory boundary, \eg, an address multiple of 64 or 128 for cache-line purposes.
 \item[array]
-the allocation size is scaled to the specified number of array elements.
+allocation with a specified number of elements.
 An array may be filled, resized, or aligned.
 \end{description}
 Table~\ref{t:StorageManagementOperations} shows the capabilities provided by C/\Celeven allocation-functions and how all the capabilities can be combined into two \CFA functions.
 \CFA storage-management functions extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size.
-Figure~\ref{f:StorageAllocation} contrasts \CFA and C storage-allocation operation performing the same operations with the same type safety.
+Figure~\ref{f:StorageAllocation} contrasts \CFA and C storage-allocation performing the same operations with the same type safety.
 
 \begin{table}
@@ -2307,5 +2342,5 @@
 \lstMakeShortInline~%
 \begin{tabular}{@{}r|r|l|l|l|l@{}}
-\multicolumn{1}{c}{}&		& \multicolumn{1}{c|}{fill}	& resize	& alignment	& array	\\
+\multicolumn{1}{c}{}&		& \multicolumn{1}{c|}{fill}	& resize	& align	& array	\\
 \hline
 C		& ~malloc~			& no			& no		& no		& no	\\
@@ -2443,5 +2478,4 @@
 \end{cfa}
 \\
-\textbf{output:}
 &
 \begin{cfa}[showspaces=true,aboveskip=0pt]
@@ -2530,22 +2564,19 @@
 \begin{cfa}[xleftmargin=3\parindentlnth,aboveskip=0pt,belowskip=0pt]
 int main( int argc, char * argv[] ) {
-	ofstream out = { "cfa-out.txt" };
 	int max = 0, val = 42;
-	stack( int ) s, t;
-
-	REPEAT_TIMED( "push_int", N, push( s, val ); )
-	TIMED( "copy_int", t = s; )
-	TIMED( "clear_int", clear( s ); )
-	REPEAT_TIMED( "pop_int", N, int v = pop( t ); max = max( v, max ); )
-	REPEAT_TIMED( "print_int", N/2, out | val | ':' | val | endl; )
-
-	pair( _Bool, char ) max = { false, '\0' }, val = { true, 'a' };
-	stack( pair( _Bool, char ) ) s, t;
-
-	REPEAT_TIMED( "push_pair", N, push( s, val ); )
-	TIMED( "copy_pair", t = s; )
-	TIMED( "clear_pair", clear( s ); )
-	REPEAT_TIMED( "pop_pair", N, pair(_Bool, char) v = pop( t ); max = max( v, max ); )
-	REPEAT_TIMED( "print_pair", N/2, out | val | ':' | val | endl; )
+	stack( int ) si, ti;
+
+	REPEAT_TIMED( "push_int", N, push( si, val ); )
+	TIMED( "copy_int", ti = si; )
+	TIMED( "clear_int", clear( si ); )
+	REPEAT_TIMED( "pop_int", N, int x = pop( ti ); if ( x > max ) max = x; )
+
+	pair( _Bool, char ) max = { (_Bool)0, '\0' }, val = { (_Bool)1, 'a' };
+	stack( pair( _Bool, char ) ) sp, tp;
+
+	REPEAT_TIMED( "push_pair", N, push( sp, val ); )
+	TIMED( "copy_pair", tp = sp; )
+	TIMED( "clear_pair", clear( sp ); )
+	REPEAT_TIMED( "pop_pair", N, pair(_Bool, char) x = pop( tp ); if ( x > max ) max = x; )
 }
 \end{cfa}
@@ -2677,4 +2708,19 @@
 \subsection{Control Structures / Declarations / Literals}
 
+Java has default fall through like C/\CC.
+Pascal/Ada/Go/Rust do not have default fall through.
+\Csharp does not have fall through but still requires a break.
+Python uses dictionary mapping. \\
+\CFA choose is like Rust match.
+
+Java has labelled break/continue. \\
+Languages with and without exception handling.
+
+Alternative C declarations. \\
+Different references \\
+Constructors/destructors
+
+0/1 Literals \\
+user defined: D, Objective-C
 
 \section{Conclusion and Future Work}
@@ -2683,5 +2729,5 @@
 While other programming languages purport to be a better C, they are in fact new and interesting languages in their own right, but not C extensions.
 The purpose of this paper is to introduce \CFA, and showcase language features that illustrate the \CFA type-system and approaches taken to achieve the goal of evolutionary C extension.
-The contributions are a powerful type-system using parametric polymorphism and overloading, generic types, and tuples, which all have complex interactions.
+The contributions are a powerful type-system using parametric polymorphism and overloading, generic types, tuples, advanced control structures, and extended declarations, which all have complex interactions.
 The work is a challenging design, engineering, and implementation exercise.
 On the surface, the project may appear as a rehash of similar mechanisms in \CC.
@@ -2690,5 +2736,5 @@
 Finally, we demonstrate that \CFA performance for some idiomatic cases is better than C and close to \CC, showing the design is practically applicable.
 
-There is ongoing work on a wide range of \CFA feature extensions, including arrays with size, exceptions, concurrent primitives, modules, and user-defined conversions.
+There is ongoing work on a wide range of \CFA feature extensions, including arrays with size, user-defined conversions, concurrent primitives, and modules.
 (While all examples in the paper compile and run, a public beta-release of \CFA will take another 8--12 months to finalize these additional extensions.)
 In addition, there are interesting future directions for the polymorphism design.
@@ -2703,6 +2749,6 @@
 \section{Acknowledgments}
 
-The authors would like to recognize the design assistance of Glen Ditchfield, Richard Bilson, and Thierry Delisle on the features described in this paper, and thank Magnus Madsen for feedback in the writing.
-This work is supported through a corporate partnership with Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are funded by the Natural Sciences and Engineering Research Council of Canada.
+The authors would like to recognize the design assistance of Glen Ditchfield, Richard Bilson, Thierry Delisle, and Andrew Beach on the features described in this paper, and thank Magnus Madsen for feedback in the writing.
+This work is supported through a corporate partnership with Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are partially funded by the Natural Sciences and Engineering Research Council of Canada.
 
 % the first author's \grantsponsor{NSERC-PGS}{NSERC PGS D}{http://www.nserc-crsng.gc.ca/Students-Etudiants/PG-CS/BellandPostgrad-BelletSuperieures_eng.asp} scholarship.
Index: doc/papers/general/evaluation/Makefile
===================================================================
--- doc/papers/general/evaluation/Makefile	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/evaluation/Makefile	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -2,7 +2,11 @@
 CFA = cfa
 DEPFLAGS = -MMD -MP
+ifdef DBG
+CFLAGS = -O0 -ggdb -DN=500
+else
 CFLAGS = -O2
 ifdef N
 CFLAGS += -DN=$(N)
+endif
 endif
 CXXFLAGS = $(CFLAGS) --std=c++14
@@ -27,14 +31,14 @@
 	$(COMPILE.cfa) $(OUTPUT_OPTION) -c $<
 
-COBJS = c-stack.o c-pair.o c-print.o c-bench.o
+COBJS = c-stack.o c-pair.o c-bench.o
 CPPOBJS = cpp-bench.o
 CPPVOBJS = cpp-vstack.o cpp-vbench.o
-CFAOBJS = cfa-stack.o cfa-pair.o cfa-print.o cfa-bench.o
+CFAOBJS = cfa-stack.o cfa-pair.o cfa-bench.o
 
 ${COBJS} ${CPPOBJS} ${CPPVOBJS} ${CFAOBJS} : ${MAKEFILE_NAME}
 
 CFILES = bench.h $(patsubst c-bench.h,,$(COBJS:.o=.h)) $(COBJS:.o=.c)
-CPPFILES = bench.hpp cpp-stack.hpp cpp-pair.hpp cpp-print.hpp $(CPPOBJS:.o=.cpp)
-CPPVFILES = bench.hpp object.hpp cpp-vprint.hpp $(patsubst cpp-vbench.hpp,,$(CPPVOBJS:.o=.hpp)) $(CPPVOBJS:.o=.cpp)
+CPPFILES = bench.hpp cpp-stack.hpp cpp-pair.hpp $(CPPOBJS:.o=.cpp)
+CPPVFILES = bench.hpp object.hpp $(patsubst cpp-vbench.hpp,,$(CPPVOBJS:.o=.hpp)) $(CPPVOBJS:.o=.cpp)
 CFAFILES = bench.h $(patsubst cfa-bench.h,,$(CFAOBJS:.o=.h)) $(CFAOBJS:.o=.c)
 
Index: doc/papers/general/evaluation/bench.h
===================================================================
--- doc/papers/general/evaluation/bench.h	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/evaluation/bench.h	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -5,5 +5,8 @@
 long ms_between(clock_t start, clock_t end) { return (end - start) / (CLOCKS_PER_SEC / 1000); }
 
+#ifndef N
 #define N 40000000
+#endif
+
 #define TIMED(name, code) { \
 	volatile clock_t _start, _end; \
Index: doc/papers/general/evaluation/bench.hpp
===================================================================
--- doc/papers/general/evaluation/bench.hpp	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/evaluation/bench.hpp	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -6,5 +6,8 @@
 long ms_between(clock_t start, clock_t end) { return (end - start) / (CLOCKS_PER_SEC / 1000); }
 
+#ifndef N
 static const int N = 40000000;
+#endif
+
 #define TIMED(name, code) { \
 	volatile clock_t _start, _end; \
Index: doc/papers/general/evaluation/c-bench.c
===================================================================
--- doc/papers/general/evaluation/c-bench.c	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/evaluation/c-bench.c	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -4,5 +4,4 @@
 #include "c-pair.h"
 #include "c-stack.h"
-#include "c-print.h"
 
 _Bool* new_bool( _Bool b ) {
@@ -39,5 +38,4 @@
 
 int main(int argc, char** argv) {
-	FILE * out = fopen("/dev/null", "w");
 	int maxi = 0, vali = 42;
 	struct stack si = new_stack(), ti;
@@ -50,5 +48,4 @@
 		if ( *xi > maxi ) { maxi = *xi; }
 		free(xi); )
-	REPEAT_TIMED( "print_int", N/2, print( out, "dsds", vali, ":", vali, "\n" ); /***/ )
 
 	struct pair * maxp = new_pair( new_bool(0), new_char('\0') ),
@@ -67,7 +64,5 @@
 			free_pair_bool_char( xp ); /***/
 		} )
-	REPEAT_TIMED( "print_pair", N/2, print( out, "pbcspbcs", *valp, ":", *valp, "\n" ); /***/ )
 	free_pair_bool_char( maxp ); /***/
 	free_pair_bool_char( valp ); /***/
-	fclose(out);
 }
Index: doc/papers/general/evaluation/cfa-bench.c
===================================================================
--- doc/papers/general/evaluation/cfa-bench.c	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/evaluation/cfa-bench.c	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -1,28 +1,23 @@
-#include <fstream>
-#include <stdlib>
-#include <stdbool.h>
 #include "bench.h"
 #include "cfa-stack.h"
 #include "cfa-pair.h"
-#include "cfa-print.h"
 
 int main( int argc, char * argv[] ) {
-	ofstream out = { "/dev/null" };
 	int max = 0, val = 42;
-	stack( int ) s, t;
+	stack( int ) si, ti;
 
-	REPEAT_TIMED( "push_int", N, push( s, val ); )
-	TIMED( "copy_int", t = s; )
-	TIMED( "clear_int", clear( s ); )
-	REPEAT_TIMED( "pop_int", N, int x = pop( t ); max = max( x, max ); )
-	REPEAT_TIMED( "print_int", N/2, out | val | ':' | val | endl; )
+	REPEAT_TIMED( "push_int", N, push( si, val ); )
+	TIMED( "copy_int", ti = si; )
+	TIMED( "clear_int", clear( si ); )
+	REPEAT_TIMED( "pop_int", N, 
+		int x = pop( ti ); if ( x > max ) max = x; )
 
-	pair( _Bool, char ) max = { (_Bool)false, '\0' }, val = { (_Bool)true, 'a' };
-	stack( pair( _Bool, char ) ) s, t;
+	pair( _Bool, char ) max = { (_Bool)0 /***/, '\0' }, val = { (_Bool)1 /***/, 'a' };
+	stack( pair( _Bool, char ) ) sp, tp;
 
-	REPEAT_TIMED( "push_pair", N, push( s, val ); )
-	TIMED( "copy_pair", t = s; )
-	TIMED( "clear_pair", clear( s ); )
-	REPEAT_TIMED( "pop_pair", N, pair(_Bool, char) x = pop( t ); max = max( x, max ); )
-	REPEAT_TIMED( "print_pair", N/2, out | val | ':' | val | endl; )
+	REPEAT_TIMED( "push_pair", N, push( sp, val ); )
+	TIMED( "copy_pair", tp = sp; )
+	TIMED( "clear_pair", clear( sp ); )
+	REPEAT_TIMED( "pop_pair", N,
+		pair(_Bool, char) x = pop( tp ); if ( x > max ) max = x; )
 }
Index: doc/papers/general/evaluation/cfa-pair.c
===================================================================
--- doc/papers/general/evaluation/cfa-pair.c	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/evaluation/cfa-pair.c	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -36,7 +36,7 @@
 }
 
-forall(otype R, otype S)
-forall(dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, R ); ostype & ?|?( ostype &, S );  })
-ostype & ?|?( ostype & os, pair(R, S) p ) {
-	return os | '[' | p.first | ',' | p.second | ']';
-} // ?|?
+// forall(otype R, otype S)
+// forall(dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, R ); ostype & ?|?( ostype &, S );  })
+// ostype & ?|?( ostype & os, pair(R, S) p ) {
+// 	return os | '[' | p.first | ',' | p.second | ']';
+// } // ?|?
Index: doc/papers/general/evaluation/cfa-pair.h
===================================================================
--- doc/papers/general/evaluation/cfa-pair.h	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/evaluation/cfa-pair.h	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -30,5 +30,5 @@
 int ?>=?(pair(R, S) p, pair(R, S) q);
 
-forall(otype R, otype S)
-forall(dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, pair(R, S) ); })
-ostype & ?|?( ostype & os, pair(R, S) );
+// forall(otype R, otype S)
+// forall(dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, R ); ostype & ?|?( ostype &, S ); })
+// ostype & ?|?( ostype & os, pair(R, S) );
Index: doc/papers/general/evaluation/cfa-stack.c
===================================================================
--- doc/papers/general/evaluation/cfa-stack.c	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/evaluation/cfa-stack.c	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -6,8 +6,4 @@
 	stack_node(T) * next;
 };
-forall(otype T) void ?{}( stack_node(T) & node, T value, stack_node(T) * next ) {
-    node.value = value;
-    node.next = next;
-}
 
 forall(otype T) void ?{}( stack(T) & s ) { (s.head){ 0 }; }
@@ -16,10 +12,8 @@
 	stack_node(T) ** crnt = &s.head;
 	for ( stack_node(T) * next = t.head; next; next = next->next ) {
-		// *crnt = new( next->value, 0 );
-		stack_node(T)* new_node = ((stack_node(T)*)malloc());
-		(*new_node){ next->value }; /***/
+		stack_node(T)* new_node = (stack_node(T)*)malloc(); /***/
+		(*new_node){ next->value };
 		*crnt = new_node;
-		stack_node(T) * acrnt = *crnt;
-		crnt = &acrnt->next;
+		crnt = &(*crnt)->next;
 	}
 	*crnt = 0;
@@ -38,7 +32,6 @@
 
 forall(otype T) void push( stack(T) & s, T value ) {
-	// s.head = new( value, s.head );
-	stack_node(T)* new_node = ((stack_node(T)*)malloc());
-	(*new_node){ value, s.head }; /***/
+	stack_node(T)* new_node = (stack_node(T)*)malloc(); /***/
+	(*new_node){ value, s.head };
 	s.head = new_node;
 }
@@ -48,5 +41,6 @@
 	s.head = n->next;
 	T v = n->value;
-	delete( n );
+	^(*n){};
+	free( n );
 	return v;
 }
@@ -56,5 +50,6 @@
 		stack_node(T) * crnt = next;
 		next = crnt->next;
-		delete( crnt );
+		^(*crnt){};
+		free(crnt);
 	}
 	s.head = 0;
Index: doc/papers/general/evaluation/cpp-bench.cpp
===================================================================
--- doc/papers/general/evaluation/cpp-bench.cpp	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/evaluation/cpp-bench.cpp	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -1,11 +1,8 @@
 #include <algorithm>
-#include <fstream>
 #include "bench.hpp"
 #include "cpp-stack.hpp"
 #include "cpp-pair.hpp"
-#include "cpp-print.hpp"
 
 int main(int argc, char** argv) {
-	std::ofstream out{"/dev/null"};
 	int maxi = 0, vali = 42;
 	stack<int> si, ti;
@@ -15,5 +12,4 @@
 	TIMED( "clear_int", si.clear(); )
 	REPEAT_TIMED( "pop_int", N, maxi = std::max( maxi, ti.pop() ); )
-	REPEAT_TIMED( "print_int", N/2, print( out, vali, ":", vali, "\n" ); )
 
 	pair<bool, char> maxp = { false, '\0' }, valp = { true, 'a' };
@@ -24,4 +20,3 @@
 	TIMED( "clear_pair", sp.clear(); )
 	REPEAT_TIMED( "pop_pair", N, maxp = std::max( maxp, tp.pop() ); )
-	REPEAT_TIMED( "print_pair", N/2, print( out, valp, ":", valp, "\n" ); )
 }
Index: doc/papers/general/evaluation/cpp-vbench.cpp
===================================================================
--- doc/papers/general/evaluation/cpp-vbench.cpp	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/evaluation/cpp-vbench.cpp	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -1,11 +1,8 @@
 #include <algorithm>
-#include <fstream>
 #include "bench.hpp"
 #include "cpp-vstack.hpp"
-#include "cpp-vprint.hpp"
 #include "object.hpp"
 
 int main(int argc, char** argv) {
-	std::ofstream out{"/dev/null"};
 	integer maxi{ 0 }, vali{ 42 };
 	stack si, ti;
@@ -15,5 +12,4 @@
 	TIMED( "clear_int", si.clear(); )
 	REPEAT_TIMED( "pop_int", N, maxi = std::max( maxi, ti.pop()->as<integer>() ); /***/ )
-	REPEAT_TIMED( "print_int", N/2, print( out, vali, c_string{":"}, vali, c_string{"\n"} ); )
 
 	ptr<pair> maxp = make<pair>( make<boolean>(false), make<character>('\0') );
@@ -27,4 +23,3 @@
 		ptr<pair> xp = as_ptr<pair>( tp.pop() ); /***/
 		if ( *xp > *maxp ) { maxp = std::move(xp); } )
-	REPEAT_TIMED( "print_pair", N/2, print( out, valp, c_string{":"}, valp, c_string{"\n"} ); )
 }
Index: doc/papers/general/evaluation/timing.dat
===================================================================
--- doc/papers/general/evaluation/timing.dat	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ doc/papers/general/evaluation/timing.dat	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -1,11 +1,10 @@
 "400 million repetitions"	"C"	"\\CFA{}"	"\\CC{}"	"\\CC{obj}"
-"push\nint"	3002	2459	1520	3305
-"copy\nint"	2985	2057	1521	3152
-"clear\nint"	1374	827	718	1469
-"pop\nint"	1416	1221	717	5467
-"print\nint"	5656	6758	3120	3121
-"push\npair"	4214	2752	946	6826
-"copy\npair"	6127	2105	993	7330
-"clear\npair"	2881	885	711	3564
-"pop\npair"	3046	5434	783	26538
-"print\npair"	7514	10714	8717	16525
+"push\nint"	2976	2225	1522	3266
+"copy\nnt"	2932	7072	1526	3110
+"clear\nint"	1380	731	750	1488
+"pop\nint"	1444	1196	756	5156
+"push\npair"	3695	2257	953	6840
+"copy\npair"	6034	6650	994	7224
+"clear\npair"	2832	848	742	3297
+"pop\npair"	3009	5348	797	25235
+
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ src/GenPoly/Box.cc	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -163,4 +163,6 @@
 			void premutate( DeclStmt *declStmt );
 			Expression *postmutate( MemberExpr *memberExpr );
+			void premutate( AddressExpr *addrExpr );
+			Expression *postmutate( AddressExpr *addrExpr );
 			Expression *postmutate( SizeofExpr *sizeofExpr );
 			Expression *postmutate( AlignofExpr *alignofExpr );
@@ -193,4 +195,5 @@
 			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?
 		};
 
@@ -1174,5 +1177,5 @@
 			if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) {
 				if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) {
-					if ( name->get_name() == "*?" ) {
+					if ( name->name == "*?" ) {
 						Expression *ret = expr->args.front();
 						expr->args.clear();
@@ -1187,14 +1190,14 @@
 		void Pass1::premutate( AddressExpr * ) { visit_children = false; }
 		Expression * Pass1::postmutate( AddressExpr * addrExpr ) {
-			assert( addrExpr->get_arg()->result && ! addrExpr->get_arg()->get_result()->isVoid() );
+			assert( addrExpr->arg->result && ! addrExpr->arg->result->isVoid() );
 
 			bool needs = false;
-			if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->get_arg() ) ) {
-				if ( expr->result && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
-					if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
-						if ( name->get_name() == "*?" ) {
-							if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) {
-								assert( appExpr->get_function()->result );
-								FunctionType *function = getFunctionType( appExpr->get_function()->get_result() );
+			if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->arg ) ) {
+				if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) {
+					if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) {
+						if ( name->name == "*?" ) {
+							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 );
@@ -1206,12 +1209,12 @@
 			// isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
 			// out of the if condition.
-			addrExpr->arg = addrExpr->get_arg()->acceptMutator( *visitor );
+			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->get_arg()->get_result(), scopeTyVars, env );
+			bool polytype = isPolyType( addrExpr->arg->result, scopeTyVars, env );
 			if ( polytype || needs ) {
-				Expression *ret = addrExpr->get_arg();
-				delete ret->get_result();
-				ret->set_result( addrExpr->get_result()->clone() );
-				addrExpr->set_arg( 0 );
+				Expression *ret = addrExpr->arg;
+				delete ret->result;
+				ret->result = addrExpr->result->clone();
+				addrExpr->arg = nullptr;
 				delete addrExpr;
 				return ret;
@@ -1250,5 +1253,5 @@
 
 		void Pass2::addAdapters( FunctionType *functionType ) {
-			std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
+			std::list< DeclarationWithType *> &paramList = functionType->parameters;
 			std::list< FunctionType *> functions;
 			for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
@@ -1271,22 +1274,22 @@
 
 		DeclarationWithType * Pass2::postmutate( FunctionDecl *functionDecl ) {
-			FunctionType * ftype = functionDecl->get_functionType();
-			if ( ! ftype->get_returnVals().empty() && functionDecl->get_statements() ) {
-				if ( ! isPrefix( functionDecl->get_name(), "_thunk" ) && ! isPrefix( functionDecl->get_name(), "_adapter" ) ) { // xxx - remove check for prefix once thunks properly use ctor/dtors
-					assert( ftype->get_returnVals().size() == 1 );
-					DeclarationWithType * retval = ftype->get_returnVals().front();
-					if ( retval->get_name() == "" ) {
-						retval->set_name( "_retval" );
+			FunctionType * ftype = functionDecl->type;
+			if ( ! ftype->returnVals.empty() && functionDecl->statements ) {
+				if ( ! 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->get_statements()->get_kids().push_front( new DeclStmt( retval ) );
+					functionDecl->statements->kids.push_front( new DeclStmt( retval ) );
 					DeclarationWithType * newRet = retval->clone(); // for ownership purposes
-					ftype->get_returnVals().front() = newRet;
+					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->get_functionType()->get_parameters() ) {
+			for ( Declaration * param : functionDecl->type->parameters ) {
 				if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( param ) ) {
-					delete obj->get_init();
-					obj->set_init( nullptr );
+					delete obj->init;
+					obj->init = nullptr;
 				}
 			}
@@ -1584,5 +1587,13 @@
 			assert( newMemberExpr );
 
-			Type *memberType = memberExpr->member->get_type();
+			// 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
@@ -1592,6 +1603,31 @@
 			}
 
+			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;
 		}
 
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ src/SynTree/Expression.cc	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -345,25 +345,11 @@
 }
 
-namespace {
-	TypeSubstitution makeSub( Type * t ) {
-		if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( t ) ) {
-			return makeSub( refType->get_base() );
-		} else if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) {
-			return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->parameters.begin() );
-		} else if ( UnionInstType * aggInst = dynamic_cast< UnionInstType * >( t ) ) {
-			return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->parameters.begin() );
-		} else {
-			assertf( false, "makeSub expects struct or union type for aggregate, but got: %s", toString( t ).c_str() );
-		}
-	}
-}
-
-
 MemberExpr::MemberExpr( DeclarationWithType *member, Expression *aggregate ) :
 		Expression(), member(member), aggregate(aggregate) {
 	assert( member );
 	assert( aggregate );
-
-	TypeSubstitution sub( makeSub( aggregate->get_result() ) );
+	assert( aggregate->result );
+
+	TypeSubstitution sub = aggregate->result->genericSubstitution();
 	Type * res = member->get_type()->clone();
 	sub.apply( res );
Index: src/SynTree/ReferenceToType.cc
===================================================================
--- src/SynTree/ReferenceToType.cc	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ src/SynTree/ReferenceToType.cc	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -14,13 +14,14 @@
 //
 
-#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 <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
 
 class Attribute;
@@ -63,4 +64,9 @@
 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;
@@ -71,4 +77,8 @@
 
 AggregateDecl * StructInstType::getAggr() { 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 {
@@ -102,7 +112,16 @@
 }
 
+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() { 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 {
Index: src/SynTree/ReferenceType.cc
===================================================================
--- src/SynTree/ReferenceType.cc	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ src/SynTree/ReferenceType.cc	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -16,4 +16,5 @@
 #include "Type.h"
 #include "Expression.h"
+#include "TypeSubstitution.h"
 #include "Common/utility.h"
 
@@ -35,4 +36,6 @@
 }
 
+TypeSubstitution ReferenceType::genericSubstitution() const { return base->genericSubstitution(); }
+
 void ReferenceType::print( std::ostream &os, Indenter indent ) const {
 	Type::print( os, indent );
Index: src/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ src/SynTree/Type.cc	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -15,9 +15,10 @@
 #include "Type.h"
 
-#include "Attribute.h"               // for Attribute
-#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 "Attribute.h"                // for Attribute
+#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;
@@ -81,4 +82,6 @@
 int Type::referenceDepth() const { return 0; }
 
+TypeSubstitution Type::genericSubstitution() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
+
 void Type::print( std::ostream &os, Indenter indent ) const {
 	if ( ! forall.empty() ) {
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ src/SynTree/Type.h	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -178,5 +178,7 @@
 	virtual bool isComplete() const { return true; }
 
-	virtual AggregateDecl * getAggr() {	assertf( false, "Non-aggregate type: %s", toString( this ).c_str() ); }
+	virtual AggregateDecl * getAggr() { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
+
+	virtual TypeSubstitution genericSubstitution() const;
 
 	virtual Type *clone() const = 0;
@@ -329,4 +331,6 @@
 	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 ); }
@@ -406,8 +410,11 @@
 	/// 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() override;
+
+	virtual TypeSubstitution genericSubstitution() const override;
 
 	/// Looks up the members of this struct named "name" and places them into "foundDecls".
@@ -439,9 +446,12 @@
 
 	/// Accesses generic parameters of base union (NULL if none such)
-	std::list< TypeDecl * > * get_baseParameters();
+	std::list<TypeDecl*> * get_baseParameters();
+	const std::list<TypeDecl*> * get_baseParameters() const;
 
 	virtual bool isComplete() const override;
 
 	virtual AggregateDecl * getAggr() override;
+
+	virtual TypeSubstitution genericSubstitution() const override;
 
 	/// looks up the members of this union named "name" and places them into "foundDecls"
Index: src/tests/.expect/literals.x86.txt
===================================================================
--- src/tests/.expect/literals.x86.txt	(revision e5d4e5c501242024833e1ed47aa37fccc9f78b23)
+++ src/tests/.expect/literals.x86.txt	(revision 560074792e28fca668389bd92e2b25a41de50943)
@@ -522,4 +522,28 @@
 signed int __main__Fi___1(){
     __attribute__ ((unused)) signed int ___retval_main__i_1;
+    ((void)0b01101011);
+    ((void)0b01101011u);
+    ((void)0b01101011l);
+    ((void)0b01101011ll);
+    ((void)0b01101011ul);
+    ((void)0b01101011lu);
+    ((void)0b01101011ull);
+    ((void)0b01101011llu);
+    ((void)(+0b01101011));
+    ((void)(+0b01101011u));
+    ((void)(+0b01101011l));
+    ((void)(+0b01101011ll));
+    ((void)(+0b01101011ul));
+    ((void)(+0b01101011lu));
+    ((void)(+0b01101011ull));
+    ((void)(+0b01101011llu));
+    ((void)(-0b01101011));
+    ((void)(-0b01101011u));
+    ((void)(-0b01101011l));
+    ((void)(-0b01101011ll));
+    ((void)(-0b01101011ul));
+    ((void)(-0b01101011lu));
+    ((void)(-0b01101011ull));
+    ((void)(-0b01101011llu));
     ((void)01234567);
     ((void)01234567u);
@@ -1017,4 +1041,34 @@
     ((void)(-0X0123456789.0123456789P-09F));
     ((void)(-0X0123456789.0123456789P-09L));
+    ((void)((signed char )0b01101011));
+    ((void)((signed short int )0b01101011));
+    ((void)((signed int )0b01101011));
+    ((void)((signed long long int )0b01101011));
+    ((void)((__int128 )0b01101011));
+    ((void)((unsigned char )0b01101011u));
+    ((void)((signed short int )0b01101011u));
+    ((void)((unsigned int )0b01101011u));
+    ((void)((signed long long int )0b01101011u));
+    ((void)((__int128 )0b01101011u));
+    ((void)(+((signed int )((signed char )0b01101011))));
+    ((void)(+((signed int )((signed short int )0b01101011))));
+    ((void)(+((signed int )0b01101011)));
+    ((void)(+((signed long long int )0b01101011)));
+    ((void)(+((float )((__int128 )0b01101011))));
+    ((void)(+((signed int )((unsigned char )0b01101011u))));
+    ((void)(+((signed int )((signed short int )0b01101011u))));
+    ((void)(+((unsigned int )0b01101011u)));
+    ((void)(+((signed long long int )0b01101011u)));
+    ((void)(+((float )((__int128 )0b01101011u))));
+    ((void)(-((signed int )((signed char )0b01101011))));
+    ((void)(-((signed int )((signed short int )0b01101011))));
+    ((void)(-((signed int )0b01101011)));
+    ((void)(-((signed long long int )0b01101011)));
+    ((void)(-((float )((__int128 )0b01101011))));
+    ((void)(-((signed int )((unsigned char )0b01101011u))));
+    ((void)(-((signed int )((signed short int )0b01101011u))));
+    ((void)(-((unsigned int )0b01101011u)));
+    ((void)(-((signed long long int )0b01101011u)));
+    ((void)(-((float )((__int128 )0b01101011u))));
     ((void)((signed char )01234567));
     ((void)((signed short int )01234567));
