Add support for `maximum_bits` and `is_signed` on `enum`s.
diff --git a/compiler/front_end/constraints_test.py b/compiler/front_end/constraints_test.py
index ff33586..9bf5a8e 100644
--- a/compiler/front_end/constraints_test.py
+++ b/compiler/front_end/constraints_test.py
@@ -282,7 +282,7 @@
     error_type = ir.module[0].type[0].structure.field[0].type
     self.assertEqual([[
         error.error("m.emb", error_type.source_location,
-                    "Enumeration type 'Bar' cannot be 0 bits; enumerations "
+                    "Enumeration type 'Bar' cannot be 0 bits; type 'Bar' "
                     "must be between 1 and 64 bits, inclusive."),
     ]], error.filter_errors(constraints.check_constraints(ir)))
 
@@ -331,10 +331,24 @@
     error_type = ir.module[0].type[0].structure.field[0].type
     self.assertEqual([[
         error.error("m.emb", error_type.source_location,
-                    "Enumeration type 'Bar' cannot be 72 bits; enumerations "
+                    "Enumeration type 'Bar' cannot be 72 bits; type 'Bar' " +
                     "must be between 1 and 64 bits, inclusive."),
     ]], error.filter_errors(constraints.check_constraints(ir)))
 
+  def test_explicit_enumeration_size_too_big_for_small_enum(self):
+    ir = _make_ir_from_emb('[$default byte_order: "BigEndian"]\n'
+                           "struct Foo:\n"
+                           "  0 [+8]  Bar  sixty_four_bit\n"
+                           "enum Bar:\n"
+                           "  [maximum_bits: 63]\n"
+                           "  BAZ = 0\n")
+    error_type = ir.module[0].type[0].structure.field[0].type
+    self.assertEqual([[
+        error.error("m.emb", error_type.source_location,
+                    "Enumeration type 'Bar' cannot be 64 bits; type 'Bar' " +
+                    "must be between 1 and 63 bits, inclusive."),
+    ]], error.filter_errors(constraints.check_constraints(ir)))
+
   def test_explicit_size_on_fixed_size_type(self):
     ir = _make_ir_from_emb("struct Foo:\n"
                            "  0 [+1]  Byte:8  one_byte\n"
@@ -417,7 +431,8 @@
             # TODO(bolms): Try to print numbers like 2**64 in hex?  (I.e., if a
             # number is a round number in hex, but not in decimal, print in
             # hex?)
-            "Value 18446744073709551616 is out of range for enumeration.")]
+            "Value 18446744073709551616 is out of range for 64-bit unsigned " +
+            "enumeration.")]
     ], constraints.check_constraints(ir))
 
   def test_enum_value_too_low(self):
@@ -428,7 +443,8 @@
     self.assertEqual([
         [error.error(
             "m.emb", error_value.source_location,
-            "Value -9223372036854775809 is out of range for enumeration.")]
+            "Value -9223372036854775809 is out of range for 64-bit signed " +
+            "enumeration.")]
     ], constraints.check_constraints(ir))
 
   def test_enum_value_too_wide(self):
@@ -436,11 +452,12 @@
                            "enum Foo:\n"
                            "  LOW = -1\n"
                            "  HIGH = 0x8000_0000_0000_0000\n")
-    error_value = ir.module[0].type[0].enumeration.value[0].value
+    error_value = ir.module[0].type[0].enumeration.value[1].value
     self.assertEqual([[
         error.error(
             "m.emb", error_value.source_location,
-            "Value -1 is out of range for unsigned enumeration.")
+            "Value 9223372036854775808 is out of range for 64-bit signed " +
+            "enumeration.")
     ]], error.filter_errors(constraints.check_constraints(ir)))
 
   def test_enum_value_too_wide_unsigned_error_message(self):
@@ -453,7 +470,33 @@
     self.assertEqual([[
         error.error(
             "m.emb", error_value.source_location,
-            "Value 9223372036854775808 is out of range for signed enumeration.")
+            "Value 9223372036854775808 is out of range for 64-bit signed " +
+            "enumeration.")
+    ]], error.filter_errors(constraints.check_constraints(ir)))
+
+  def test_enum_value_too_wide_small_size_error_message(self):
+    ir = _make_ir_from_emb('[$default byte_order: "LittleEndian"]\n'
+                           "enum Foo:\n"
+                           "  [maximum_bits: 8]\n"
+                           "  HIGH = 0x100\n")
+    error_value = ir.module[0].type[0].enumeration.value[0].value
+    self.assertEqual([[
+        error.error(
+            "m.emb", error_value.source_location,
+            "Value 256 is out of range for 8-bit unsigned enumeration.")
+    ]], error.filter_errors(constraints.check_constraints(ir)))
+
+  def test_enum_value_too_wide_small_size_signed_error_message(self):
+    ir = _make_ir_from_emb('[$default byte_order: "LittleEndian"]\n'
+                           "enum Foo:\n"
+                           "  [maximum_bits: 8]\n"
+                           "  [is_signed: true]\n"
+                           "  HIGH = 0x80\n")
+    error_value = ir.module[0].type[0].enumeration.value[0].value
+    self.assertEqual([[
+        error.error(
+            "m.emb", error_value.source_location,
+            "Value 128 is out of range for 8-bit signed enumeration.")
     ]], error.filter_errors(constraints.check_constraints(ir)))
 
   def test_enum_value_too_wide_multiple(self):
@@ -463,15 +506,17 @@
                            "  LOW2 = -1\n"
                            "  HIGH = 0x8000_0000_0000_0000\n"
                            "  HIGH2 = 0x8000_0000_0000_0001\n")
-    error_value = ir.module[0].type[0].enumeration.value[0].value
-    error_value2 = ir.module[0].type[0].enumeration.value[1].value
+    error_value = ir.module[0].type[0].enumeration.value[2].value
+    error_value2 = ir.module[0].type[0].enumeration.value[3].value
     self.assertEqual([
         [error.error(
             "m.emb", error_value.source_location,
-            "Value -2 is out of range for unsigned enumeration.")],
+            "Value 9223372036854775808 is out of range for 64-bit signed " +
+            "enumeration.")],
         [error.error(
             "m.emb", error_value2.source_location,
-            "Value -1 is out of range for unsigned enumeration.")]
+            "Value 9223372036854775809 is out of range for 64-bit signed " +
+            "enumeration.")]
     ], error.filter_errors(constraints.check_constraints(ir)))
 
   def test_enum_value_too_wide_multiple_signed_error_message(self):
@@ -487,11 +532,11 @@
     self.assertEqual([
         [error.error(
             "m.emb", error_value.source_location,
-            "Value 9223372036854775808 is out of range for signed "
+            "Value 9223372036854775808 is out of range for 64-bit signed "
             "enumeration.")],
         [error.error(
             "m.emb", error_value2.source_location,
-            "Value 9223372036854775809 is out of range for signed "
+            "Value 9223372036854775809 is out of range for 64-bit signed "
             "enumeration.")]
     ], error.filter_errors(constraints.check_constraints(ir)))
 
@@ -501,15 +546,55 @@
                            "  LOW = -1\n"
                            "  HIGH = 0x8000_0000_0000_0000\n"
                            "  HIGH2 = 0x1_0000_0000_0000_0000\n")
-    error_value = ir.module[0].type[0].enumeration.value[0].value
+    error_value1 = ir.module[0].type[0].enumeration.value[1].value
     error_value2 = ir.module[0].type[0].enumeration.value[2].value
     self.assertEqual([
         [error.error(
-            "m.emb", error_value.source_location,
-            "Value -1 is out of range for unsigned enumeration.")],
+            "m.emb", error_value1.source_location,
+            "Value 9223372036854775808 is out of range for 64-bit signed " +
+            "enumeration.")],
         [error.error(
             "m.emb", error_value2.source_location,
-            "Value 18446744073709551616 is out of range for enumeration.")]
+            "Value 18446744073709551616 is out of range for 64-bit signed " +
+            "enumeration.")]
+    ], error.filter_errors(constraints.check_constraints(ir)))
+
+  def test_enum_value_explicitly_signed_error_message(self):
+    ir = _make_ir_from_emb('[$default byte_order: "LittleEndian"]\n'
+                           "enum Foo:\n"
+                           "  [is_signed: true]\n"
+                           "  HIGH = 0x8000_0000_0000_0000\n"
+                           "  HIGH2 = 0x1_0000_0000_0000_0000\n")
+    error_value0 = ir.module[0].type[0].enumeration.value[0].value
+    error_value1 = ir.module[0].type[0].enumeration.value[1].value
+    self.assertEqual([
+        [error.error(
+            "m.emb", error_value0.source_location,
+            "Value 9223372036854775808 is out of range for 64-bit signed " +
+            "enumeration.")],
+        [error.error(
+            "m.emb", error_value1.source_location,
+            "Value 18446744073709551616 is out of range for 64-bit signed " +
+            "enumeration.")]
+    ], error.filter_errors(constraints.check_constraints(ir)))
+
+  def test_enum_value_explicitly_unsigned_error_message(self):
+    ir = _make_ir_from_emb('[$default byte_order: "LittleEndian"]\n'
+                           "enum Foo:\n"
+                           "  [is_signed: false]\n"
+                           "  LOW = -1\n"
+                           "  HIGH = 0x8000_0000_0000_0000\n"
+                           "  HIGH2 = 0x1_0000_0000_0000_0000\n")
+    error_value0 = ir.module[0].type[0].enumeration.value[0].value
+    error_value2 = ir.module[0].type[0].enumeration.value[2].value
+    self.assertEqual([
+        [error.error(
+            "m.emb", error_value0.source_location,
+            "Value -1 is out of range for 64-bit unsigned enumeration.")],
+        [error.error(
+            "m.emb", error_value2.source_location,
+            "Value 18446744073709551616 is out of range for 64-bit unsigned " +
+            "enumeration.")]
     ], error.filter_errors(constraints.check_constraints(ir)))
 
   def test_explicit_non_byte_size_array_element(self):