Index: doc/bibliography/pl.bib
===================================================================
--- doc/bibliography/pl.bib	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ doc/bibliography/pl.bib	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -3088,4 +3088,13 @@
     note	= {WikipediA},
     howpublished= {\url{http://www.akkadia.org/drepper/tls.pdf}},
+}
+
+@misc{DARPA24,
+    contributer	= {pabuhr@plg},
+    title	= {Eliminating Memory Safety Vulnerabilities Once and For All},
+    author	= {Defense Advanced Research Projects Agency},
+    year	= 2024,
+    month	= jul,
+    howpublished= {\url{https://www.darpa.mil/news-events/2024-07-31a}},
 }
 
@@ -7686,4 +7695,12 @@
 }
 
+@misc{WhiteHouse24,
+    contributer	= {pabuhr@plg},
+    title	= {Part {II}: Securing the Building Blocks of Cyberspace},
+    author	= {U.S. Federal Government},
+    year	= 2024,
+    howpublished= {\url{https://www.whitehouse.gov/wp-content/uploads/2024/02/Final-ONCD-Technical-Report.pdf}},
+}
+
 @inproceedings{Chen07,
     keywords	= {chip multiprocessors, constructive cache sharing, parallel depth first, scheduling algorithms, thread granularity, work stealing, working set profiling},
Index: doc/theses/jiada_liang_MMath/test1.cfa
===================================================================
--- doc/theses/jiada_liang_MMath/test1.cfa	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ doc/theses/jiada_liang_MMath/test1.cfa	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -1,4 +1,5 @@
 #include <fstream.hfa>									// sout
 #include <stdlib.hfa>									// ato
+#include <enum.hfa>
 
 // integral
@@ -9,4 +10,5 @@
 enum( Letter ) Greek { Alph = A, Beta = B, Gamma = G, /* more enums */ Zeta = Z }; // alphabet intersection
 
+// integral
 enum( char ) Currency { Dollar = '$', Cent = '¢', Yen = '¥', Pound = '£', Euro = 'E' }; // iso-latin-1
 enum( Currency ) Europe { Euro = Currency.Euro, Pound = Currency.Pound };
@@ -33,9 +35,14 @@
 
 enum() Mode { O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC, O_APPEND };
-Mode iomode = O_RDONLY;
-//bool b = iomode == O_RDONLY || iomode < O_APPEND;	// disallowed
-//int www = iomode;	// disallowed
+Mode mode = O_RDONLY;
+void opaque() {
+bool b = mode == O_RDONLY || mode < O_APPEND;	// disallowed
+//int www = mode;	// disallowed
+}
 
 enum( char * ) Colour { Red = "red", Green = "green", Blue = "blue"  };
+
+enum E1 { A1, B1, C1 = A1, D1 = B1 };
+enum(float) E2 { A2 = 3.5, B2 = 4.5, C2 = A, D2 = B };
 
 void fred() {
@@ -45,17 +52,23 @@
 //greek = A;								// disallowed
 
-	for ( Greek l = Alph; posn(l) <= posn(Gamma); l = succ( l ) ) {
+	for ( Greek l = Alph; posn(l) < posn(Gamma); l = succ( l ) ) {
 		printf( "%s %c %d\n", label( l ), value( l ), posn( l ) );
 	}
-	for ( Currency c = Dollar; posn(c) <= posn(Currency.Euro); c = succ( c ) ) {
+	for ( Currency c = Dollar; posn(c) < posn(Currency.Euro); c = succ( c ) ) {
 		printf( "%s %c %d\n", label( c ), value( c ), posn( c ) );
 	}
 }
 
-
-enum( char * ) Names { Fred = "FRED", Mary = "MARY", Jane = "JANE" };
-enum( char * ) Names2 { inline Names, Jack = "JACK", Jill = "JILL" };
-enum( char * ) Names3 { inline Names2, Sue = "SUE", Tom = "TOM" };
-
+enum( const char * ) Names { Fred = "FRED", Mary = "MARY", Jane = "JANE" };
+enum( const char * ) Names2 { inline Names, Jack = "JACK", Jill = "JILL" };
+enum( const char * ) Names3 { inline Names2, Sue = "SUE", Tom = "TOM" };
+void bar() {
+	Names fred = Names.Fred;
+	(Names2)fred;  (Names3)fred;  (Names3)Names2.Jack;  // cast to super type
+	Names2 fred2 = fred;  Names3 fred3 = fred2; // assign to super type
+	const char * name = fred;
+	Names name = Fred;
+	sout | name | label( name ) | posn( name ) | value( name );
+}
 void f( Names n ) { sout | "Name" | posn( n ); }
 void g( Names2 );
@@ -63,9 +76,17 @@
 void j( char * );
 
-enum color { red, blue, green };
-//color c = 0;
-//color c = 1;
-color c = 2;
-int w = red;
+enum CColour { Red, Blue, Green };
+CColour c0 = 0;
+CColour c1 = 1;
+CColour c = 2;
+int w = Red;
+
+void coo() {
+	enum(int) Color { Red, Blue, Green };
+	Colour c = Red;
+	sout | countof( Colour ) | Countof( c );
+//	sout | Countof( Colour );
+	sout | countof( c );
+}
 
 // enum(int) Week ! { Mon, Tue, Wed, Thu = 10, Fri, Sat, Sun };
@@ -79,12 +100,57 @@
 // }
 
+void baz() {
+	enum(int) Count { First, Second, Third/* = First*/, Fourth/* = Second*/ };
+	enum CCount { First, Second, Third/* = First*/, Fourth/* = Second*/ };
+	Count cnt = Second;
+	CCount ccnt = Second;
+	if ( cnt < Third ) sout | "less than Third";
+	if ( cnt ) sout | "XXX";
+	if ( ccnt ) sout | "YYY";
+	enum(float) F {WWW = 0.0};
+	F f;
+	if ( f ) sout | "FFF";
+	bool ?!=?( Name n, zero_t ) { sout | "DDD";  return n != Fred; }
+	Name n = Mary;
+	if ( n ) sout | "NAME";
+	choose( cnt ) {
+		case First: sout | "First";
+		case Second: sout | "Second";
+		case Third: sout | "Third";
+		case Fourth: sout | "Fourth";
+	}
+//	for (d; Week) { sout | d; }
+//	for (p; +~=Planet) { sout | p; }
+	for ( cx; Count ) { sout | cx | nonl; } sout | nl;
+	for ( cx; +~= Count ) { sout | cx | nonl; } sout | nl;
+	for ( cx; -~= Count ) { sout | cx | nonl; } sout | nl;
+	for ( Count cx = lowerBound();; ) {
+		sout | cx | nonl;
+	  if ( cx == upperBound() ) break;
+		cx = succ( cx );
+	}
+	sout | nl;
+}
+
 int main() {
 	fred();
-	Names name = Fred;
+	Names name = Names.Fred;
 //	f( name );
 
 	int jane_pos = posn( Names.Jane );
-	char * jane_value = value( Names.Jane );
-	char * jane_label = label( Names.Jane );
+	const char * jane_value = value( Names.Jane );
+	const char * jane_label = label( Names.Jane );
 	sout | Names.Jane | posn( Names.Jane) | label( Names.Jane ) | value( Names.Jane );
+
+	bar();
+	baz();
+	coo();
+
+	enum Ex { Ax, Bx, Cx, Nx };
+	float H1[Nx] = { [Ax] : 3.4, [Bx] : 7.1, [Cx] : 0.01 }; // C
+//	float H2[Ex] = { [Ax] : 3.4, [Bx] : 7.1, [Cx] : 0.01 }; // CFA
+
+	enum(int) E { A = 3 } e = A;
+	sout | A | label( A ) | posn( A ) | value( A );
+	sout | e | label( e ) | posn( e ) | value( e );
 }
Index: c/theses/jiada_liang_MMath/test2.cc
===================================================================
--- doc/theses/jiada_liang_MMath/test2.cc	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ 	(revision )
@@ -1,8 +1,0 @@
-struct unit {};
-void foo( void );
-unit bar( unit );
-int main() {
-	unit u;
-	foo( foo() );
-	bar( bar( u ) );
-}
Index: c/theses/jiada_liang_MMath/test20.cfa
===================================================================
--- doc/theses/jiada_liang_MMath/test20.cfa	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ 	(revision )
@@ -1,10 +1,0 @@
-int main() {
-//	enum { X = 3, Y = 3.5 };
-//	enum(char *) { Z = "abc" };
-	enum { X = 3, Y = 3.5, Z = "abc" };
-
-	int i = X;
-	double d = Y;
-	printf( "%g\n", d );
-	const char * str = Z;
-}
Index: c/theses/jiada_liang_MMath/test3.cfa
===================================================================
--- doc/theses/jiada_liang_MMath/test3.cfa	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ 	(revision )
@@ -1,8 +1,0 @@
-enum Week ! { Mon, Tue, Wed, Thu = 10, Fri, Sat, Sun };
-enum RGB ! { Red, Green, Blue };
-void foo() {
-	Week week = Week.Mon;
-	week = Week.Sat;
-	RGB rgb = RGB.Red;
-	rgb = RGB.Blue;
-}
Index: doc/theses/mike_brooks_MMath/background.tex
===================================================================
--- doc/theses/mike_brooks_MMath/background.tex	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ doc/theses/mike_brooks_MMath/background.tex	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -2,4 +2,38 @@
 
 Since this work builds on C, it is necessary to explain the C mechanisms and their shortcomings for array, linked list, and string.
+
+
+\section{Ill-typed expressions}
+
+C reports many ill-typed expressions as warnings.
+For example, these attempts to assign @y@ to @x@ and vice-versa are obviously ill-typed.
+\lstinput{12-15}{bkgd-c-tyerr.c}
+with warnings:
+\begin{cfa}
+warning: assignment to 'float *' from incompatible pointer type 'void (*)(void)'
+warning: assignment to 'void (*)(void)' from incompatible pointer type 'float *'
+\end{cfa}
+Similarly,
+\lstinput{17-19}{bkgd-c-tyerr.c}
+with warning:
+\begin{cfa}
+warning: passing argument 1 of 'f' from incompatible pointer type
+note: expected 'void (*)(void)' but argument is of type 'float *'
+\end{cfa}
+with a segmentation fault at runtime.
+Clearly, @gcc@ understands these ill-typed case, and yet allows the program to compile, which seems inappropriate.
+Compiling with flag @-Werror@, which turns warnings into errors, is often too strong, because some warnings are just warnings, \eg unused variable.
+In the following discussion, ``ill-typed'' means giving a nonzero @gcc@ exit condition with a message that discusses typing.
+Note, \CFA's type-system rejects all these ill-typed cases as type mismatch errors.
+
+% That @f@'s attempt to call @g@ fails is not due to 3.14 being a particularly unlucky choice of value to put in the variable @pi@.
+% Rather, it is because obtaining a program that includes this essential fragment, yet exhibits a behaviour other than "doomed to crash," is a matter for an obfuscated coding competition.
+
+% A "tractable syntactic method for proving the absence of certain program behaviours by classifying phrases according to the kinds of values they compute"*1 rejected the program.
+% The behaviour (whose absence is unprovable) is neither minor nor unlikely.
+% The rejection shows that the program is ill-typed.
+% 
+% Yet, the rejection presents as a GCC warning.
+% *1  TAPL-pg1 definition of a type system
 
 
Index: doc/theses/mike_brooks_MMath/intro.tex
===================================================================
--- doc/theses/mike_brooks_MMath/intro.tex	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ doc/theses/mike_brooks_MMath/intro.tex	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -1,26 +1,29 @@
 \chapter{Introduction}
 
-All modern programming languages provide three high-level containers (collection): array, linked-list, and string.
-Often array is part of the programming language, while linked-list is built from pointer types, and string from a combination of array and linked-list.
-For all three types, there is some corresponding mechanism for iterating through the structure, where the iterator flexibility varies with the kind of structure and ingenuity of the iterator implementor.
+All modern programming languages provide three high-level containers (collections): array, linked-list, and string.
+Often array is part of the programming language, while linked-list is built from (recursive) pointer types, and string from a combination of array and linked-list.
+For all three types, languages supply varying degrees of high-level mechanism for manipulating these objects at the bulk level and at the component level, such as array copy, slicing and iterating.
+
+This work looks at extending these three foundational container types in the programming language \CFA, which is a new dialect of the C programming language.
+A primary goal of \CFA~\cite{Cforall} is 99\% backward compatibility with C, while maintaining a look and feel that matches with C programmer experience and intuition.
+This goal requires ``thinking inside the box'' to engineer new features that ``work and play'' with C and its massive legacy code-base.
+An additional goal is balancing good performance with safety.
 
 
 \section{Array}
 
-An array provides a homogeneous container with $O(1)$ access to elements using subscripting (some form of pointer arithmetic).
+An array provides a homogeneous container with $O(1)$ access to elements using subscripting.
 The array size can be static, dynamic but fixed after creation, or dynamic and variable after creation.
 For static and dynamic-fixed, an array can be stack allocated, while dynamic-variable requires the heap.
-Because array layout has contiguous components, subscripting is a computation.
-However, the computation can exceed the array bounds resulting in programming errors and security violations~\cite{Elliott18, Blache19, Ruef19, Oorschot23}.
-The goal is to provide good performance with safety.
+Because array layout has contiguous components, subscripting is a computation (some form of pointer arithmetic).
 
 
 \section{Linked list}
 
-A linked-list provides a homogeneous container often with $O(log N)$/$O(N)$ access to elements using successor and predecessor operations.
+A linked-list provides a homogeneous container often with $O(log N)$/$O(N)$ access to elements using successor and predecessor operations that normally involve pointer chasing.
 Subscripting by value is sometimes available, \eg hash table.
 Linked types are normally dynamically sized by adding/removing nodes using link fields internal or external to the elements (nodes).
 If a programming language allows pointer to stack storage, linked-list types can be allocated on the stack;
-otherwise, elements are heap allocated and explicitly/implicitly managed.
+otherwise, elements are heap allocated with explicitly/implicitly managed.
 
 
@@ -28,15 +31,30 @@
 
 A string provides a dynamic array of homogeneous elements, where the elements are often human-readable characters.
-What differentiates a string from other types in that its operations work on blocks of elements for scanning and changing the elements, rather than accessing individual elements, \eg @index@ and @substr@.
+What differentiates a string from other types in that its operations work on blocks of elements for scanning and changing, \eg @index@ and @substr@.
 Subscripting individual elements is often available.
-Often the cost of string operations is less important than the power of the operations to accomplish complex text manipulation, \eg search, analysing, composing, and decomposing.
+Therefore, the cost of string operations is less important than the power of the operations to accomplish complex text manipulation, \eg search, analysing, composing, and decomposing.
 The dynamic nature of a string means storage is normally heap allocated but often implicitly managed, even in unmanaged languages.
+Often string management is separate from heap management, \ie strings roll their own heap.
 
 
 \section{Motivation}
 
-The goal of this work is to introduce safe and complex versions of array, link lists, and strings into the programming language \CFA~\cite{Cforall}, which is based on C.
-Unfortunately, to make C better, while retaining a high level of backwards compatibility, requires a significant knowledge of C's design.
-Hence, it is assumed the reader has a medium knowledge of C or \CC, on which extensive new C knowledge is built.
+The primary motivation for this work is two fold:
+\begin{enumerate}[leftmargin=*]
+\item
+These three aspects of C are extremely difficult to understand, teach, and get right because they are correspondingly extremely low level.
+Providing higher-level versions of these containers in \CFA is a major component of the primary goal.
+\item
+These three aspects of C cause the greatest safety issues because there are few or no safe guards when a programmer misunderstands or misuses these features~\cite{Elliott18, Blache19, Ruef19, Oorschot23}.
+Estimates suggest 50\%~\cite{Mendio24} of total reported open-source vulnerabilities occur in C resulting from errors using these facilities (memory errors), providing the major hacker attack-vectors.
+\end{enumerate}
+Both White House~\cite{WhiteHouse24} and DARPA~\cite{DARPA24} recently released a recommendation to move away from C and \CC, because of cybersecurity threats exploiting vulnerabilities in these older languages.
+Hardening these three types goes a long way to make the majority of C programs safer.
+
+
+While multiple new languages purport to be systems languages replacing C, the reality is that rewriting massive C code-bases is impractical and a non-starter if the new runtime uses garage collection.
+Furthermore, these languages must still interact with the underlying C operating system through fragile, type-unsafe, interlanguage-communication.
+Switching to \CC is equally impractical as its complex and interdependent type-system (\eg objects, inheritance, templates) means idiomatic \CC code is difficult to use from C, and C programmers must expend significant effort learning \CC.
+Hence, rewriting and retraining costs for these languages can be prohibitive for companies with a large C software-base (Google, Apple, Microsoft, Amazon, AMD, Nvidia).
 
 
@@ -46,49 +64,15 @@
 However, most programming languages are only partially explained by standard's manuals.
 When it comes to explaining how C works, the definitive source is the @gcc@ compiler, which is mimicked by other C compilers, such as Clang~\cite{clang}.
-Often other C compilers must mimic @gcc@ because a large part of the C library (runtime) system contains @gcc@ features.
-While some key aspects of C need to be explained by quoting from the language reference manual, to illustrate definite program semantics, I devise a program, whose behaviour exercises the point at issue, and shows its behaviour.
+Often other C compilers must mimic @gcc@ because a large part of the C library (runtime) system (@glibc@ on Linux) contains @gcc@ features.
+While some key aspects of C need to be explained by quoting from the language reference manual, to illustrate definite program semantics, my approach in this thesis is to devise a program, whose behaviour exercises a point at issue, and shows its behaviour.
 These example programs show
-\begin{itemize}
-	\item the compiler accepts or rejects certain syntax,
+\begin{itemize}[leftmargin=*]
+	\item if the compiler accepts or rejects certain syntax,
 	\item prints output to buttress a claim of behaviour,
-	\item executes without triggering any embedded assertions testing pre/post-assertions or invariants.
+	\item or executes without triggering any embedded assertions testing pre/post-assertions or invariants.
 \end{itemize}
 This work has been tested across @gcc@ versions 8--12 and clang version 10 running on ARM, AMD, and Intel architectures.
 Any discovered anomalies among compilers or versions is discussed.
-In all case, I do not argue that my sample of major Linux compilers is doing the right thing with respect to the C standard.
-
-
-\subsection{Ill-typed expressions}
-
-C reports many ill-typed expressions as warnings.
-For example, these attempts to assign @y@ to @x@ and vice-versa are obviously ill-typed.
-\lstinput{12-15}{bkgd-c-tyerr.c}
-with warnings:
-\begin{cfa}
-warning: assignment to 'float *' from incompatible pointer type 'void (*)(void)'
-warning: assignment to 'void (*)(void)' from incompatible pointer type 'float *'
-\end{cfa}
-Similarly,
-\lstinput{17-19}{bkgd-c-tyerr.c}
-with warning:
-\begin{cfa}
-warning: passing argument 1 of 'f' from incompatible pointer type
-note: expected 'void (*)(void)' but argument is of type 'float *'
-\end{cfa}
-with a segmentation fault at runtime.
-Clearly, @gcc@ understands these ill-typed case, and yet allows the program to compile, which seems inappropriate.
-Compiling with flag @-Werror@, which turns warnings into errors, is often too strong, because some warnings are just warnings, \eg unsed variable.
-In the following discussion, ``ill-typed'' means giving a nonzero @gcc@ exit condition with a message that discusses typing.
-Note, \CFA's type-system rejects all these ill-typed cases as type mismatch errors.
-
-% That @f@'s attempt to call @g@ fails is not due to 3.14 being a particularly unlucky choice of value to put in the variable @pi@.
-% Rather, it is because obtaining a program that includes this essential fragment, yet exhibits a behaviour other than "doomed to crash," is a matter for an obfuscated coding competition.
-
-% A "tractable syntactic method for proving the absence of certain program behaviours by classifying phrases according to the kinds of values they compute"*1 rejected the program.
-% The behaviour (whose absence is unprovable) is neither minor nor unlikely.
-% The rejection shows that the program is ill-typed.
-% 
-% Yet, the rejection presents as a GCC warning.
-% *1  TAPL-pg1 definition of a type system
+In all case, it is never clear whether the \emph{truth} lies in the compiler or the C standard.
 
 
Index: doc/theses/mike_brooks_MMath/string.tex
===================================================================
--- doc/theses/mike_brooks_MMath/string.tex	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ doc/theses/mike_brooks_MMath/string.tex	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -1,5 +1,7 @@
 \chapter{String}
 
-\section{String}
+
+
+
 
 \subsection{Logical overlap}
Index: doc/theses/mike_brooks_MMath/uw-ethesis.bib
===================================================================
--- doc/theses/mike_brooks_MMath/uw-ethesis.bib	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ doc/theses/mike_brooks_MMath/uw-ethesis.bib	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -114,2 +114,11 @@
     pages	= {53-60},
 }
+
+
+@misc{Mendio24,
+    contributer	= {pabuhr@plg},
+    title	= {What are the most secure programming languages?},
+    author	= {Mend.io (White Source Ltd.)},
+    year	= 2024,
+    howpublished= {\url{https://www.mend.io/most-secure-programming-languages}},
+}
Index: libcfa/src/concurrency/io/call.cfa.in
===================================================================
--- libcfa/src/concurrency/io/call.cfa.in	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ libcfa/src/concurrency/io/call.cfa.in	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -214,5 +214,7 @@
 	__attribute__((unused)) bool parked;
 	parked = wait( future );
+#if defined(CFA_HAVE_LINUX_IO_URING_H)
 	__STATS__(false, if(!parked) io.submit.nblk += 1; )
+#endif
 	if( future.result < 0 ) {{
 		errno = -future.result;
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ src/AST/Expr.hpp	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -11,5 +11,5 @@
 // Last Modified By : Peter A. Buhr
 // Created On       : Fri May 10 10:30:00 2019
-// Update Count     : 7
+// Update Count     : 8
 //
 
@@ -86,5 +86,5 @@
 
 		/// initializes from other InferUnion
-		void init_from( const InferUnion& o ) {
+		void init_from( const InferUnion & o ) {
 			if (o.data.resnSlots) {
 				data.resnSlots = new ResnSlots(*o.data.resnSlots);
@@ -96,5 +96,5 @@
 
 		/// initializes from other InferUnion (move semantics)
-		void init_from( InferUnion&& o ) {
+		void init_from( InferUnion && o ) {
 			data.resnSlots = o.data.resnSlots;
 			data.inferParams = o.data.inferParams;
@@ -104,13 +104,13 @@
 
 		InferUnion() : mode(Empty), data() {}
-		InferUnion( const InferUnion& o ) : mode( o.mode ), data() { init_from( o ); }
-		InferUnion( InferUnion&& o ) : mode( o.mode ), data() { init_from( std::move(o) ); }
-		InferUnion& operator= ( const InferUnion& ) = delete;
-		InferUnion& operator= ( InferUnion&& ) = delete;
+		InferUnion( const InferUnion & o ) : mode( o.mode ), data() { init_from( o ); }
+		InferUnion( InferUnion && o ) : mode( o.mode ), data() { init_from( std::move(o) ); }
+		InferUnion & operator= ( const InferUnion & ) = delete;
+		InferUnion & operator= ( InferUnion && ) = delete;
 
 		bool hasSlots() const { return data.resnSlots; }
 		bool hasParams() const { return data.inferParams; }
 
-		ResnSlots& resnSlots() {
+		ResnSlots & resnSlots() {
 			if (!data.resnSlots) {
 				data.resnSlots = new ResnSlots();
@@ -119,5 +119,5 @@
 		}
 
-		const ResnSlots& resnSlots() const {
+		const ResnSlots & resnSlots() const {
 			if (data.resnSlots) {
 				return *data.resnSlots;
@@ -127,5 +127,5 @@
 		}
 
-		InferredParams& inferParams() {
+		InferredParams & inferParams() {
 			if (!data.inferParams) {
 				data.inferParams = new InferredParams();
@@ -134,5 +134,5 @@
 		}
 
-		const InferredParams& inferParams() const {
+		const InferredParams & inferParams() const {
 			if (data.inferParams) {
 				return *data.inferParams;
@@ -669,5 +669,5 @@
 	ptr<ApplicationExpr> callExpr;
 
-	ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call )
+	ImplicitCopyCtorExpr( const CodeLocation & loc, const ApplicationExpr * call )
 	: Expr( loc, call->result ), callExpr(call) { assert( call ); assert(call->result); }
 
Index: src/CodeGen/CodeGenerator.cpp
===================================================================
--- src/CodeGen/CodeGenerator.cpp	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ src/CodeGen/CodeGenerator.cpp	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -79,5 +79,5 @@
 		currentLocation.first_line += 2;
 	} else {
-		output << "\n# " << to.first_line << " \"" << to.filename
+		output << "\n# " << to.first_line << " \"" << to.filename.c_str()
 		       << "\"\n" << indent;
 		currentLocation = to;
Index: src/Common/CodeLocation.hpp
===================================================================
--- src/Common/CodeLocation.hpp	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ src/Common/CodeLocation.hpp	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -17,9 +17,9 @@
 
 #include <iostream>
-#include <string>
+#include "Symbol.hpp"
 
 struct CodeLocation {
 	int first_line = -1, first_column = -1, last_line = -1, last_column = -1;
-	std::string filename = "";
+	Symbol filename = "";
 
 	/// Create a new unset CodeLocation.
@@ -46,6 +46,6 @@
 
 	bool startsBefore( CodeLocation const & other ) const {
-		if( filename < other.filename ) return true;
-		if( filename > other.filename ) return false;
+		if( filename.str() < other.filename.str() ) return true;
+		if( filename.str() > other.filename.str() ) return false;
 
 		if( first_line < other.first_line ) return true;
@@ -72,4 +72,4 @@
 inline std::ostream & operator<<( std::ostream & out, const CodeLocation & location ) {
 	// Column number ":1" allows IDEs to parse the error message and position the cursor in the source text.
-	return location.isSet() ? out << location.filename << ":" << location.first_line << ":1 " : out;
+	return location.isSet() ? out << location.filename.str() << ":" << location.first_line << ":1 " : out;
 }
Index: src/Common/Symbol.cpp
===================================================================
--- src/Common/Symbol.cpp	(revision d1f505458756015a841bcf6550a2229cffceffb9)
+++ src/Common/Symbol.cpp	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -0,0 +1,148 @@
+#include "Symbol.hpp"
+
+#include <unordered_map>
+
+// This class (and the member-like helpers) are the implementation details
+// of the Symbol class. It is just does reference counting to share strings.
+// It is designed for maintainablity, but also to optimize the copy cases.
+class SymbolData {
+public:
+	std::string const value;
+	// As long as we are using a pointer sized counter,
+	// overflow should never be an issue.
+	std::size_t refCount;
+
+	SymbolData(std::string const & value, std::size_t refCount) :
+		value(value), refCount(refCount)
+	{}
+};
+
+namespace {
+	template<typename T>
+	struct IndirectHash {
+		std::hash<T> hasher;
+		std::size_t operator()(T const * const & val) const {
+			return hasher(*val);
+		}
+	};
+
+	template<typename T>
+	struct IndirectEqualTo {
+		std::equal_to<T> equals;
+		bool operator()(T const * const & lhs, T const * const & rhs) const {
+			return equals(*lhs, *rhs);
+		}
+	};
+} // namespace
+
+using SymbolMap = std::unordered_map<std::string const *, SymbolData *,
+	IndirectHash<std::string>, IndirectEqualTo<std::string>>;
+
+/// Get the storage for the map of symbol data.
+// Note: This is basically static memory, but wrapping the data in a function
+// causes the constructor to run with the proper timing.
+static SymbolMap & getAllSymbols() {
+	static SymbolMap allSymbols;
+	return allSymbols;
+}
+
+/// Clear out all unsed SymbolData.
+static void eraseUnused() {
+	SymbolMap & allSymbols = getAllSymbols();
+
+	auto it = allSymbols.begin();
+	while (it != allSymbols.end()) {
+		if (it->second->refCount) {
+			++it;
+		} else {
+			delete it->second;
+			it = allSymbols.erase(it);
+		}
+	}
+}
+
+/// Convert a string to a new or existing SymbolData.
+static SymbolData * getSymbolData(std::string const & str) {
+	SymbolMap & allSymbols = getAllSymbols();
+
+	// If there is an existing symbol, re-use it.
+	auto it = allSymbols.find(&str);
+	if (it != allSymbols.end()) {
+		SymbolData * data = it->second;
+		++data->refCount;
+		return data;
+	}
+
+	// If these is no existing symbol, create the required data.
+	SymbolData * data = new SymbolData(str, 1);
+	allSymbols.insert(std::make_pair(&data->value, data));
+	return data;
+}
+
+/// Reduce reference count and free the SymbolData as needed.
+static void decSymbolData(SymbolData * data) {
+	// First comes the actual decrement.
+	--data->refCount;
+
+	// If it has hit zero, remove it from the map.
+	if (0 == data->refCount) {
+		eraseUnused();
+	}
+}
+
+Symbol::Symbol() : data(getSymbolData(std::string())) {}
+
+Symbol::Symbol(std::string const & str) : data(getSymbolData(str)) {}
+
+Symbol::Symbol(char const * str) : data(getSymbolData(str)) {}
+
+Symbol::Symbol(Symbol const & other) : data(other.data) {
+	++data->refCount;
+}
+
+Symbol::Symbol(Symbol && other) : data(other.data) {
+	++data->refCount;
+}
+
+Symbol::~Symbol() {
+	decSymbolData(data);
+}
+
+Symbol & Symbol::operator=(std::string const & str) {
+	SymbolData * dat = getSymbolData(str);
+	decSymbolData(data);
+	data = dat;
+	return *this;
+}
+
+Symbol & Symbol::operator=(char const * str) {
+	return this->operator=(std::string(str));
+}
+
+Symbol & Symbol::operator=(Symbol const & other) {
+	++other.data->refCount;
+	decSymbolData(data);
+	data = other.data;
+	return *this;
+}
+
+Symbol & Symbol::operator=(Symbol && other) {
+	Symbol const & ref = other;
+	return this->operator=(ref);
+}
+
+bool Symbol::operator==(Symbol const & other) const {
+	return data == other.data;
+}
+
+bool Symbol::operator!=(Symbol const & other) const {
+	return data != other.data;
+}
+
+std::string const & Symbol::str() const {
+	return data->value;
+}
+
+char const * Symbol::c_str() const {
+	return data->value.c_str();
+}
Index: src/Common/Symbol.hpp
===================================================================
--- src/Common/Symbol.hpp	(revision d1f505458756015a841bcf6550a2229cffceffb9)
+++ src/Common/Symbol.hpp	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <string>
+
+// Internal Type:
+class SymbolData;
+
+/// A Symbol is an interned string, where the characters are 'hidden'.
+class Symbol final {
+	SymbolData * data;
+public:
+	/// Create a Symbol for the empty string.
+	Symbol();
+
+	Symbol(std::string const &);
+	Symbol(char const *);
+	Symbol(Symbol const &);
+	Symbol(Symbol &&);
+
+	~Symbol();
+
+	Symbol & operator=(std::string const &);
+	Symbol & operator=(char const *);
+	Symbol & operator=(Symbol const &);
+	Symbol & operator=(Symbol &&);
+
+	bool operator==(Symbol const &) const;
+	bool operator!=(Symbol const &) const;
+
+	std::string const & str() const;
+	char const * c_str() const;
+};
Index: src/Common/module.mk
===================================================================
--- src/Common/module.mk	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ src/Common/module.mk	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -48,4 +48,6 @@
 	Common/Stats/Time.cpp \
 	Common/Stats/Time.hpp \
+	Common/Symbol.cpp \
+	Common/Symbol.hpp \
 	Common/ToString.hpp \
 	Common/UniqueName.cpp \
Index: src/GenPoly/Lvalue.cpp
===================================================================
--- src/GenPoly/Lvalue.cpp	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ src/GenPoly/Lvalue.cpp	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -10,6 +10,6 @@
 // Created On       : Thu Sep 15 14:08:00 2022
 // Last Modified By : Andrew Beach
-// Last Modified On : Wed Oct  6  9:59:00 2022
-// Update Count     : 0
+// Last Modified On : Mon Aug 12 18:07:00 2024
+// Update Count     : 1
 //
 
@@ -119,4 +119,6 @@
 /// Replace all reference types with pointer types.
 struct ReferenceTypeElimination final {
+	ast::SizeofExpr const * previsit( ast::SizeofExpr const * expr );
+	ast::AlignofExpr const * previsit( ast::AlignofExpr const * expr );
 	ast::Type const * postvisit( ast::ReferenceType const * type );
 };
@@ -603,4 +605,18 @@
 }
 
+ast::SizeofExpr const * ReferenceTypeElimination::previsit(
+		ast::SizeofExpr const * expr ) {
+	if ( expr->expr ) return expr;
+	return ast::mutate_field( expr, &ast::SizeofExpr::type,
+		expr->type->stripReferences() );
+}
+
+ast::AlignofExpr const * ReferenceTypeElimination::previsit(
+		ast::AlignofExpr const * expr ) {
+	if ( expr->expr ) return expr;
+	return ast::mutate_field( expr, &ast::AlignofExpr::type,
+		expr->type->stripReferences() );
+}
+
 ast::Type const * ReferenceTypeElimination::postvisit(
 		ast::ReferenceType const * type ) {
Index: src/InitTweak/FixInit.cpp
===================================================================
--- src/InitTweak/FixInit.cpp	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ src/InitTweak/FixInit.cpp	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -731,8 +731,8 @@
 	try {
 		mutLast->expr = makeCtorDtor( "?{}", ret, mutLast->expr );
-	} catch(...) {
+	} catch (...) {
 		std::cerr << "*CFA internal error: ";
 		std::cerr << "can't resolve implicit constructor";
-		std::cerr << " at " << stmtExpr->location.filename;
+		std::cerr << " at " << stmtExpr->location.filename.c_str();
 		std::cerr << ":" << stmtExpr->location.first_line << std::endl;
 
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ src/Parser/parser.yy	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul 26 14:09:30 2024
-// Update Count     : 6733
+// Last Modified On : Tue Aug 13 11:25:16 2024
+// Update Count     : 6740
 //
 
@@ -952,5 +952,5 @@
 		}
 	| COUNTOF unary_expression
-		{  $$ = new ExpressionNode( new ast::CountExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
+		{ $$ = new ExpressionNode( new ast::CountExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
 	| COUNTOF '(' type_no_function ')'
 		{ $$ = new ExpressionNode( new ast::CountExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
@@ -1626,12 +1626,18 @@
 enum_key:
 	type_name
-		{	typedefTable.makeTypedef( *$1->symbolic.name, "enum_type_nobody 1" );
-			$$ = DeclarationNode::newEnum( $1->symbolic.name, nullptr, false, false ); }
+		{
+			typedefTable.makeTypedef( *$1->symbolic.name, "enum_type_nobody 1" );
+			$$ = DeclarationNode::newEnum( $1->symbolic.name, nullptr, false, false );
+		}
 	| ENUM identifier
-		{	typedefTable.makeTypedef( *$2, "enum_type_nobody 2" );
-			$$ = DeclarationNode::newEnum( $2, nullptr, false, false ); }
+		{
+			typedefTable.makeTypedef( *$2, "enum_type_nobody 2" );
+			$$ = DeclarationNode::newEnum( $2, nullptr, false, false );
+		}
 	| ENUM type_name
-		{	typedefTable.makeTypedef( *$2->symbolic.name, "enum_type_nobody 3" );
-			$$ = DeclarationNode::newEnum( $2->symbolic.name, nullptr, false, false ); }
+		{
+			typedefTable.makeTypedef( *$2->symbolic.name, "enum_type_nobody 3" );
+			$$ = DeclarationNode::newEnum( $2->symbolic.name, nullptr, false, false );
+		}
 	;
 
@@ -1849,8 +1855,8 @@
 
 handler_clause:
-	handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
-		{ $$ = new ClauseNode( build_catch( yylloc, $1, $4, $6, $8 ) ); }
-	| handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
-		{ $$ = $1->set_last( new ClauseNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); }
+	handler_key '(' exception_declaration handler_predicate_opt ')' compound_statement
+		{ $$ = new ClauseNode( build_catch( yylloc, $1, $3, $4, $6 ) ); }
+	| handler_clause handler_key '(' exception_declaration handler_predicate_opt ')' compound_statement
+		{ $$ = $1->set_last( new ClauseNode( build_catch( yylloc, $2, $4, $5, $7 ) ) ); }
 	;
 
@@ -2850,5 +2856,7 @@
 
 enumerator_list:
-	visible_hide_opt identifier_or_type_name enumerator_value_opt
+	// empty
+		{ SemanticError( yylloc, "enumeration must have a minimum of one enumerator, empty enumerator list is meaningless." );  $$ = nullptr; }
+	| visible_hide_opt identifier_or_type_name enumerator_value_opt
 		{ $$ = DeclarationNode::newEnumValueGeneric( $2, $3 ); }
 	| INLINE type_name
@@ -3155,6 +3163,6 @@
 	'|' identifier_or_type_name '(' type_list ')'
 		{ $$ = DeclarationNode::newTraitUse( $2, $4 ); }
-	| '|' '{' push trait_declaration_list pop '}'
-		{ $$ = $4; }
+	| '|' '{' trait_declaration_list '}'
+		{ $$ = $3; }
 	// | '|' '(' push type_parameter_list pop ')' '{' push trait_declaration_list pop '}' '(' type_list ')'
 	// 	{ SemanticError( yylloc, "Generic data-type assertion is currently unimplemented." ); $$ = nullptr; }
@@ -3208,17 +3216,17 @@
 	| forall TRAIT identifier_or_type_name '{' '}'		// alternate
 		{ $$ = DeclarationNode::newTrait( $3, $1, nullptr ); }
-	| TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
+	| TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' trait_declaration_list '}'
 		{
 			SemanticWarning( yylloc, Warning::DeprecTraitSyntax );
-			$$ = DeclarationNode::newTrait( $2, $4, $8 );
-		}
-	| forall TRAIT identifier_or_type_name '{' push trait_declaration_list pop '}' // alternate
-		{ $$ = DeclarationNode::newTrait( $3, $1, $6 ); }
+			$$ = DeclarationNode::newTrait( $2, $4, $7 );
+		}
+	| forall TRAIT identifier_or_type_name '{' trait_declaration_list '}' // alternate
+		{ $$ = DeclarationNode::newTrait( $3, $1, $5 ); }
 	;
 
 trait_declaration_list:									// CFA
 	trait_declaration
-	| trait_declaration_list pop push trait_declaration
-		{ $$ = $1->set_last( $4 ); }
+	| trait_declaration_list trait_declaration
+		{ $$ = $1->set_last( $2 ); }
 	;
 
@@ -3231,13 +3239,16 @@
 	cfa_variable_specifier
 	| cfa_function_specifier
-	| cfa_trait_declaring_list pop ',' push identifier_or_type_name
-		{ $$ = $1->set_last( $1->cloneType( $5 ) ); }
+	| cfa_trait_declaring_list ',' identifier_or_type_name
+		{ $$ = $1->set_last( $1->cloneType( $3 ) ); }
 	;
 
 trait_declaring_list:									// CFA
-	type_specifier declarator
+		// Cannot declare an aggregate or enumeration in a trait.
+	type_specifier_nobody declarator
 		{ $$ = $2->addType( $1 ); }
-	| trait_declaring_list pop ',' push declarator
-		{ $$ = $1->set_last( $1->cloneBaseType( $5 ) ); }
+	| trait_declaring_list ',' declarator
+		{ $$ = $1->set_last( $1->cloneBaseType( $3 ) ); }
+	| error
+		{ SemanticError( yylloc, "Possible cause is declaring an aggregate or enumeration type in a trait." ); $$ = nullptr; }
 	;
 
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -1281,4 +1281,11 @@
 				// count one safe conversion for each value that is thrown away
 				thisCost.incSafe( discardedValues );
+
+				// See Aaron Moss, page 47; this reasoning does not hold since implicit conversions
+				// can create the same resolution issue. The C intrinsic interpretations are pruned
+				// immediately for the lowest cost option regardless of result type. Related code in
+				// postvisit (UntypedExpr).
+				// Cast expression costs are updated now to use the general rules.
+				/*
 				// select first on argument cost, then conversion cost
 				if ( cand->cost < minExprCost || ( cand->cost == minExprCost && thisCost < minCastCost ) ) {
@@ -1289,7 +1296,14 @@
 				// ambigious case, still output candidates to print in error message
 				if ( cand->cost == minExprCost && thisCost == minCastCost ) {
+				*/
+				cand->cost += thisCost;
+				if (cand->cost < minExprCost) {
+					minExprCost = cand->cost;
+					matches.clear();
+				}
+				if (cand->cost == minExprCost) {
 					CandidateRef newCand = std::make_shared<Candidate>(
 						restructureCast( cand->expr, toType, castExpr->isGenerated ),
-						copy( cand->env ), std::move( open ), std::move( need ), cand->cost + thisCost);
+						copy( cand->env ), std::move( open ), std::move( need ), cand->cost);
 					// currently assertions are always resolved immediately so this should have no effect.
 					// if this somehow changes in the future (e.g. delayed by indeterminate return type)
Index: tests/.expect/sizeof.txt
===================================================================
--- tests/.expect/sizeof.txt	(revision d1f505458756015a841bcf6550a2229cffceffb9)
+++ tests/.expect/sizeof.txt	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -0,0 +1,2 @@
+char  : 1 1
+char &: 1 1
Index: tests/sizeof.cfa
===================================================================
--- tests/sizeof.cfa	(revision d1f505458756015a841bcf6550a2229cffceffb9)
+++ tests/sizeof.cfa	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -0,0 +1,11 @@
+// Testing non-polymorphic sizeof (and alignof) expressions:
+
+#include <fstream.hfa>
+
+int main(int argc, char * argv[]) {
+	char val = 'c';
+	char & ref = val;
+	// It could check against "char *", but it should always be different.
+	sout | "char  : " | sizeof(val) | alignof(val);
+	sout | "char &: " | sizeof(ref) | alignof(ref);
+}
Index: tests/time.cfa
===================================================================
--- tests/time.cfa	(revision 26d40a153b36433771afa35935935e66c9bedb04)
+++ tests/time.cfa	(revision d1f505458756015a841bcf6550a2229cffceffb9)
@@ -10,6 +10,6 @@
 // Created On       : Tue Mar 27 17:24:56 2018
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul 19 08:06:59 2024
-// Update Count     : 75
+// Last Modified On : Tue Aug 13 09:09:47 2024
+// Update Count     : 76
 //
 
@@ -18,9 +18,9 @@
 #include <stdlib.h>										// putenv
 
-extern "C" size_t malloc_unfreed() { return 1024; }		// guess at unfreed storage from putenv
+extern "C" size_t malloc_unfreed() { return 2048; }		// guess at unfreed storage from putenv/tzset
 
 int main() {
 	// Set fixed time location to obtain repeatable output where ever run.
-	putenv( "TZ=America/Toronto" );						// set fixed time zone
+	putenv( "TZ=America/Toronto" );						// pick fixed time zone
 	// tzset has the stupidest interface I have ever seen.
 	tzset();											// set time zone
