Index: doc/proposals/enums.md
===================================================================
--- doc/proposals/enums.md	(revision 9a01745e06266b363221bee8eedb6c563702cf33)
+++ doc/proposals/enums.md	(revision 262a8640f3e6326f4901f564082c318c28cc6943)
@@ -8,5 +8,6 @@
 --------------
 Because Cforall enumerations are encoded using their position, it can be
-difficult to give them a stable encoding. The
+difficult to give them a stable encoding, this is important in seperate
+compilation.
 
 The example (provided by Gregor Richards), is a system header that defines
@@ -42,4 +43,29 @@
 (instead of a subset of int) is used in the index operation.
 
+```cfa
+enum() Colour {
+  Red,
+  Violet,
+  Blue,
+  Green
+  Yellow,
+  Orange,
+};
+
+// Declare an array with an index of an enumeration:
+int jarsOfPaint[Colour] = {0};
+
+// Index the array:
+printf("I have %d jars of blue paint.\n", jarsOfPaint[Blue]);
+jarsOfPaint[Green] = 3;
+jarsOfPaint[Red] += 1;
+
+// Use the function for higher order programming:
+int (*lookup)(int collection[Colour], Colour key) = ?[?];
+
+// ERROR! Use the enumeration index for safety:
+jarsOfPaint[0] = 0;
+```
+
 Although described differently, this is actually a generalization of typed
 enumerations, as it can be used to safely represent a constant of any type
@@ -80,5 +106,5 @@
 Or one of the new safer Cforall arrays, as the features could be combined.
 
-(Previously, a compined declaration to declare both an enumeration and
+(Previously, a combined declaration to declare both an enumeration and
 an enumerated array was proposed. That only covers the simple case that
 typed enumerations already cover.)
@@ -90,4 +116,15 @@
 generalized to work with the other features of ranges, such as going over
 just part of the enumeration (see Ranges in doc/proposals/iterators.md).
+
+This will work best with some alias labels that mark out the beginning of
+ranges. That is the ranges within the enum will often have to be an
+intended part of the interface.
+
+```cfa
+for ( kind : DataKind.BeginIntegers +~ DataKind.EndIntegers ) { ... }
+```
+
+Writing the declaration is a bit tricker, because of the lack of aliasing,
+but this should echo a common C pattern.
 
 Flag Set Enumerations
@@ -111,4 +148,18 @@
 ```
 
+Some example usages:
+```cfa
+// If it is exactly Up/Upwards, then set exactly Down
+if ( Upwards == dirs ) {
+  dirs = Down
+// Otherwise, if a vertical is set, unset them:
+} else if ( Vertical & dirs ) {
+  dirs = dirs & ~Vertical;
+// Otherwise, if any direction is set then also set Up:
+} else if ( dirs ) {
+  dirs |= Up;
+}
+```
+
 Uses the existing enumeration syntax, except that all initializers must be
 bitwise expressions, using only the operators |, & and ~ and, as leaf values,
@@ -132,2 +183,24 @@
 
 Note: Scoping rules are also waiting on the namespacing and module system.
+
+Feature (and Storage) Control
+-----------------------------
+Right now features are very coursely grouped. You have exactly three options
+for your enumeration. However since there are more than two features this
+means there are some combinations you cannot have.
+
+For instance, labels (which are mostly useful for generating debug output)
+are not available for C style enum, but for both of the new Cforall enums,
+opaque and typed. However, there is no innate connection between the
+additional type safety of the opaque enum or the associated values/payloads
+of the typed enums.
+
+Enumerations do interact with on feature that shows this orthagonality,
+and that is the scoping "no export" marker, that can be applied to any
+enumeration to change the visibility rules of the enumeration and does not
+change anything else.
+
+This is not urgent, just not using the features you don't want is almost as
+clear and the compile-time, binary-size and runtime costs are all good enough
+for now (and some day all of those may have to be improved even when the
+feature is being used). Isolating independent features is just good design.
Index: src/CodeGen/OperatorTable.cpp
===================================================================
--- src/CodeGen/OperatorTable.cpp	(revision 9a01745e06266b363221bee8eedb6c563702cf33)
+++ src/CodeGen/OperatorTable.cpp	(revision 262a8640f3e6326f4901f564082c318c28cc6943)
@@ -76,7 +76,10 @@
 	}
 
-	if ( inputName.find_first_of( "?^*+-!", 0, 1 ) == std::string::npos ) return nullptr; // prefilter
-	const OperatorInfo * ret = inputTable.find( inputName )->second;
+	// Filter out non-operator names:
+	if ( inputName.find_first_of( "?^*+-!", 0, 1 ) == std::string::npos ) return nullptr;
+	auto entry = inputTable.find( inputName );
 	// This can only happen if an invalid identifier name has been used.
+	assertf( entry != inputTable.end(), "Not a real operator: %s\n", inputName.c_str() );
+	const OperatorInfo * ret = entry->second;
 	assert( ret );
 	return ret;
Index: src/Validate/ReplaceTypedef.cpp
===================================================================
--- src/Validate/ReplaceTypedef.cpp	(revision 9a01745e06266b363221bee8eedb6c563702cf33)
+++ src/Validate/ReplaceTypedef.cpp	(revision 262a8640f3e6326f4901f564082c318c28cc6943)
@@ -10,6 +10,6 @@
 // Created On       : Tue Jun 29 14:59:00 2022
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Dec 14 16:11:51 2023
-// Update Count     : 4
+// Last Modified On : Mon Dec 16 20:50:42 2024
+// Update Count     : 5
 //
 
@@ -135,8 +135,6 @@
 };
 static bool dimensionPresenceMismatched( const ast::Type * t0, const ast::Type * t1) {
-	std::vector<const ast::ArrayType *> at0s = std::move(
-		ast::Pass<ArrayTypeExtractor>::read( t0 ) );
-	std::vector<const ast::ArrayType *> at1s = std::move(
-		ast::Pass<ArrayTypeExtractor>::read( t1 ) );
+	std::vector<const ast::ArrayType *> at0s = ast::Pass<ArrayTypeExtractor>::read( t0 );
+	std::vector<const ast::ArrayType *> at1s = ast::Pass<ArrayTypeExtractor>::read( t1 );
 	assert( at0s.size() == at1s.size() );
 	for (size_t i = 0; i < at0s.size(); i++) {
Index: tests/.expect/attributes.arm64.txt
===================================================================
--- tests/.expect/attributes.arm64.txt	(revision 9a01745e06266b363221bee8eedb6c563702cf33)
+++ tests/.expect/attributes.arm64.txt	(revision 262a8640f3e6326f4901f564082c318c28cc6943)
@@ -1337,2 +1337,81 @@
     return _X4_retS3Vad_1;
 }
+__attribute__ (( noreturn )) void _X4fredFv___1(void){
+    __attribute__ ((unused)) signed int _X1ii_2;
+    switch ( 3 ) {
+        case 2:
+            {
+                {
+                    ((void)4);
+                }
+
+            }
+        case 1:
+            {
+                {
+                    ((void)3);
+                }
+
+            }
+    }
+
+}
+__attribute__ ((noreturn)) void _X4maryFv___1(void){
+    struct __attribute__ ((aligned(64))) S {
+        signed int _X1ii_2;
+    };
+    inline void _X12_constructorFv_S1S_autogen___2(__attribute__ ((unused)) struct S *_X4_dstS1S_2){
+        {
+            ((void)((*_X4_dstS1S_2)._X1ii_2) /* ?{} */);
+        }
+
+    }
+    inline void _X12_constructorFv_S1SS1S_autogen___2(__attribute__ ((unused)) struct S *_X4_dstS1S_2, __attribute__ ((unused)) struct S _X4_srcS1S_2){
+        {
+            ((void)((*_X4_dstS1S_2)._X1ii_2=_X4_srcS1S_2._X1ii_2) /* ?{} */);
+        }
+
+    }
+    inline void _X11_destructorFv_S1S_autogen___2(__attribute__ ((unused)) struct S *_X4_dstS1S_2){
+        {
+            ((void)((*_X4_dstS1S_2)._X1ii_2) /* ^?{} */);
+        }
+
+    }
+    inline struct S _X16_operator_assignFS1S_S1SS1S_autogen___2(__attribute__ ((unused)) struct S *_X4_dstS1S_2, __attribute__ ((unused)) struct S _X4_srcS1S_2){
+        __attribute__ ((unused)) struct S _X4_retS1S_2;
+        {
+            ((void)((*_X4_dstS1S_2)._X1ii_2=_X4_srcS1S_2._X1ii_2));
+        }
+
+        {
+            ((void)_X12_constructorFv_S1SS1S_autogen___2((&_X4_retS1S_2), (*_X4_dstS1S_2)));
+        }
+
+        return _X4_retS1S_2;
+    }
+    inline void _X12_constructorFv_S1Si_autogen___2(__attribute__ ((unused)) struct S *_X4_dstS1S_2, signed int _X1ii_2){
+        {
+            ((void)((*_X4_dstS1S_2)._X1ii_2=_X1ii_2) /* ?{} */);
+        }
+
+    }
+    __attribute__ ((unused)) signed int _X1ii_2;
+    switch ( 3 ) {
+        case 2:
+            {
+                {
+                    ((void)4);
+                }
+
+            }
+        case 1:
+            {
+                {
+                    ((void)3);
+                }
+
+            }
+    }
+
+}
Index: tests/.expect/attributes.x86.txt
===================================================================
--- tests/.expect/attributes.x86.txt	(revision 9a01745e06266b363221bee8eedb6c563702cf33)
+++ tests/.expect/attributes.x86.txt	(revision 262a8640f3e6326f4901f564082c318c28cc6943)
@@ -1337,2 +1337,81 @@
     return _X4_retS3Vad_1;
 }
+__attribute__ (( noreturn )) void _X4fredFv___1(void){
+    __attribute__ ((unused)) signed int _X1ii_2;
+    switch ( 3 ) {
+        case 2:
+            {
+                {
+                    ((void)4);
+                }
+
+            }
+        case 1:
+            {
+                {
+                    ((void)3);
+                }
+
+            }
+    }
+
+}
+__attribute__ ((noreturn)) void _X4maryFv___1(void){
+    struct __attribute__ ((aligned(64))) S {
+        signed int _X1ii_2;
+    };
+    inline void _X12_constructorFv_S1S_autogen___2(__attribute__ ((unused)) struct S *_X4_dstS1S_2){
+        {
+            ((void)((*_X4_dstS1S_2)._X1ii_2) /* ?{} */);
+        }
+
+    }
+    inline void _X12_constructorFv_S1SS1S_autogen___2(__attribute__ ((unused)) struct S *_X4_dstS1S_2, __attribute__ ((unused)) struct S _X4_srcS1S_2){
+        {
+            ((void)((*_X4_dstS1S_2)._X1ii_2=_X4_srcS1S_2._X1ii_2) /* ?{} */);
+        }
+
+    }
+    inline void _X11_destructorFv_S1S_autogen___2(__attribute__ ((unused)) struct S *_X4_dstS1S_2){
+        {
+            ((void)((*_X4_dstS1S_2)._X1ii_2) /* ^?{} */);
+        }
+
+    }
+    inline struct S _X16_operator_assignFS1S_S1SS1S_autogen___2(__attribute__ ((unused)) struct S *_X4_dstS1S_2, __attribute__ ((unused)) struct S _X4_srcS1S_2){
+        __attribute__ ((unused)) struct S _X4_retS1S_2;
+        {
+            ((void)((*_X4_dstS1S_2)._X1ii_2=_X4_srcS1S_2._X1ii_2));
+        }
+
+        {
+            ((void)_X12_constructorFv_S1SS1S_autogen___2((&_X4_retS1S_2), (*_X4_dstS1S_2)));
+        }
+
+        return _X4_retS1S_2;
+    }
+    inline void _X12_constructorFv_S1Si_autogen___2(__attribute__ ((unused)) struct S *_X4_dstS1S_2, signed int _X1ii_2){
+        {
+            ((void)((*_X4_dstS1S_2)._X1ii_2=_X1ii_2) /* ?{} */);
+        }
+
+    }
+    __attribute__ ((unused)) signed int _X1ii_2;
+    switch ( 3 ) {
+        case 2:
+            {
+                {
+                    ((void)4);
+                }
+
+            }
+        case 1:
+            {
+                {
+                    ((void)3);
+                }
+
+            }
+    }
+
+}
