authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-02 22:31:42-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-02 22:32:39-05:00
log137c8f5e8a6023db24f90555e968b592a4b843e4
tree822547a6857ad24dad7ed8c7d26720d17b7bcce7
parent98237f7c0ba62099e85a8caf8fc09039845b224e

ability to set tag values of enums

also remove support for enums with 0 values closes #305

13 files changed, 451 insertions(+), 146 deletions(-)

doc/langref.html.in+1-1
...@@ -5709,7 +5709,7 @@ VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" Typ...@@ -5709,7 +5709,7 @@ VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" Typ
57095709
5710ContainerMember = (ContainerField | FnDef | GlobalVarDecl)5710ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
57115711
5712ContainerField = Symbol option(":" Expression) ","5712ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression ","
57135713
5714UseDecl = "use" Expression ";"5714UseDecl = "use" Expression ";"
57155715
src/all_types.hpp+6-4
...@@ -98,7 +98,7 @@ struct ConstParent {...@@ -98,7 +98,7 @@ struct ConstParent {
98};98};
9999
100struct ConstEnumValue {100struct ConstEnumValue {
101 uint64_t tag;101 BigInt tag;
102 ConstExprValue *payload;102 ConstExprValue *payload;
103};103};
104104
...@@ -108,7 +108,7 @@ struct ConstStructValue {...@@ -108,7 +108,7 @@ struct ConstStructValue {
108};108};
109109
110struct ConstUnionValue {110struct ConstUnionValue {
111 uint64_t tag;111 BigInt tag;
112 ConstExprValue *payload;112 ConstExprValue *payload;
113 ConstParent parent;113 ConstParent parent;
114};114};
...@@ -346,14 +346,14 @@ struct TldCompTime {...@@ -346,14 +346,14 @@ struct TldCompTime {
346struct TypeEnumField {346struct TypeEnumField {
347 Buf *name;347 Buf *name;
348 TypeTableEntry *type_entry;348 TypeTableEntry *type_entry;
349 uint32_t value;349 BigInt value;
350 uint32_t gen_index;350 uint32_t gen_index;
351};351};
352352
353struct TypeUnionField {353struct TypeUnionField {
354 Buf *name;354 Buf *name;
355 TypeTableEntry *type_entry;355 TypeTableEntry *type_entry;
356 uint32_t value;356 BigInt value;
357 uint32_t gen_index;357 uint32_t gen_index;
358};358};
359359
...@@ -780,6 +780,7 @@ struct AstNodeStructField {...@@ -780,6 +780,7 @@ struct AstNodeStructField {
780 VisibMod visib_mod;780 VisibMod visib_mod;
781 Buf *name;781 Buf *name;
782 AstNode *type;782 AstNode *type;
783 AstNode *value;
783};784};
784785
785struct AstNodeStringLiteral {786struct AstNodeStringLiteral {
...@@ -1014,6 +1015,7 @@ struct TypeTableEntryEnum {...@@ -1014,6 +1015,7 @@ struct TypeTableEntryEnum {
1014 TypeEnumField *fields;1015 TypeEnumField *fields;
1015 bool is_invalid; // true if any fields are invalid1016 bool is_invalid; // true if any fields are invalid
1016 TypeTableEntry *tag_type;1017 TypeTableEntry *tag_type;
1018 TypeTableEntry *tag_int_type;
1017 LLVMTypeRef union_type_ref;1019 LLVMTypeRef union_type_ref;
10181020
1019 ScopeDecls *decls_scope;1021 ScopeDecls *decls_scope;
src/analyze.cpp+182-52
...@@ -1390,30 +1390,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {...@@ -1390,30 +1390,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1390 return;1390 return;
1391 }1391 }
13921392
1393 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);1393 TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type;
1394 if (decl_node->data.container_decl.init_arg_expr != nullptr) {
1395 TypeTableEntry *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
1396 if (type_is_invalid(wanted_tag_int_type)) {
1397 enum_type->data.enumeration.is_invalid = true;
1398 } else if (wanted_tag_int_type->id != TypeTableEntryIdInt) {
1399 enum_type->data.enumeration.is_invalid = true;
1400 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
1401 buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
1402 } else if (wanted_tag_int_type->data.integral.is_signed) {
1403 enum_type->data.enumeration.is_invalid = true;
1404 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
1405 buf_sprintf("expected unsigned integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
1406 } else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) {
1407 enum_type->data.enumeration.is_invalid = true;
1408 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
1409 buf_sprintf("'%s' too small to hold all bits; must be at least '%s'",
1410 buf_ptr(&wanted_tag_int_type->name), buf_ptr(&tag_int_type->name)));
1411 } else {
1412 tag_int_type = wanted_tag_int_type;
1413 }
1414 }
1415
1416
1417 TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type);1394 TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type);
1418 enum_type->data.enumeration.tag_type = tag_type_entry;1395 enum_type->data.enumeration.tag_type = tag_type_entry;
14191396
...@@ -1683,7 +1660,6 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {...@@ -1683,7 +1660,6 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
1683 TypeTableEntry *field_type = type_struct_field->type_entry;1660 TypeTableEntry *field_type = type_struct_field->type_entry;
16841661
1685 ensure_complete_type(g, field_type);1662 ensure_complete_type(g, field_type);
1686
1687 if (type_is_invalid(field_type)) {1663 if (type_is_invalid(field_type)) {
1688 struct_type->data.structure.is_invalid = true;1664 struct_type->data.structure.is_invalid = true;
1689 break;1665 break;
...@@ -2121,6 +2097,18 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {...@@ -2121,6 +2097,18 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
21212097
2122 assert(!enum_type->data.enumeration.fields);2098 assert(!enum_type->data.enumeration.fields);
2123 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;2099 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;
2100 if (field_count == 0) {
2101 add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
2102
2103 enum_type->data.enumeration.src_field_count = field_count;
2104 enum_type->data.enumeration.fields = nullptr;
2105 enum_type->data.enumeration.is_invalid = true;
2106 enum_type->data.enumeration.zero_bits_loop_flag = false;
2107 enum_type->data.enumeration.gen_field_count = 0;
2108 enum_type->data.enumeration.zero_bits_known = true;
2109 return;
2110 }
2111
2124 enum_type->data.enumeration.src_field_count = field_count;2112 enum_type->data.enumeration.src_field_count = field_count;
2125 enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);2113 enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
21262114
...@@ -2128,14 +2116,69 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {...@@ -2128,14 +2116,69 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
21282116
2129 Scope *scope = &enum_type->data.enumeration.decls_scope->base;2117 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
21302118
2119 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
2120 occupied_tag_values.init(field_count);
2121
2122 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
2123
2124 if (decl_node->data.container_decl.init_arg_expr != nullptr) {
2125 TypeTableEntry *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
2126 if (type_is_invalid(wanted_tag_int_type)) {
2127 enum_type->data.enumeration.is_invalid = true;
2128 } else if (wanted_tag_int_type->id != TypeTableEntryIdInt) {
2129 enum_type->data.enumeration.is_invalid = true;
2130 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
2131 buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
2132 } else if (wanted_tag_int_type->data.integral.is_signed) {
2133 enum_type->data.enumeration.is_invalid = true;
2134 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
2135 buf_sprintf("expected unsigned integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
2136 } else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) {
2137 enum_type->data.enumeration.is_invalid = true;
2138 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
2139 buf_sprintf("'%s' too small to hold all bits; must be at least '%s'",
2140 buf_ptr(&wanted_tag_int_type->name), buf_ptr(&tag_int_type->name)));
2141 } else {
2142 tag_int_type = wanted_tag_int_type;
2143 }
2144 }
2145 enum_type->data.enumeration.tag_int_type = tag_int_type;
2146
2131 uint32_t gen_field_index = 0;2147 uint32_t gen_field_index = 0;
2132 for (uint32_t i = 0; i < field_count; i += 1) {2148 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
2133 AstNode *field_node = decl_node->data.container_decl.fields.at(i);2149 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
2134 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];2150 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
2135 type_enum_field->name = field_node->data.struct_field.name;2151 type_enum_field->name = field_node->data.struct_field.name;
2136 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);2152 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
2137 type_enum_field->type_entry = field_type;2153 type_enum_field->type_entry = field_type;
2138 type_enum_field->value = i;2154
2155 AstNode *tag_value = field_node->data.struct_field.value;
2156
2157 // In this first pass we resolve explicit tag values.
2158 // In a second pass we will fill in the unspecified ones.
2159 if (tag_value != nullptr) {
2160 IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2161 if (result_inst->value.type->id == TypeTableEntryIdInvalid) {
2162 enum_type->data.enumeration.is_invalid = true;
2163 continue;
2164 }
2165 assert(result_inst->value.special != ConstValSpecialRuntime);
2166 assert(result_inst->value.type->id == TypeTableEntryIdInt);
2167 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
2168 if (entry == nullptr) {
2169 bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint);
2170 } else {
2171 Buf *val_buf = buf_alloc();
2172 bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);
2173
2174 ErrorMsg *msg = add_node_error(g, tag_value,
2175 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
2176 add_error_note(g, msg, entry->value,
2177 buf_sprintf("other occurrence here"));
2178 enum_type->data.enumeration.is_invalid = true;
2179 continue;
2180 }
2181 }
21392182
2140 type_ensure_zero_bits_known(g, field_type);2183 type_ensure_zero_bits_known(g, field_type);
2141 if (type_is_invalid(field_type)) {2184 if (type_is_invalid(field_type)) {
...@@ -2155,6 +2198,34 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {...@@ -2155,6 +2198,34 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
2155 }2198 }
2156 }2199 }
21572200
2201 // Now iterate again and populate the unspecified tag values
2202 uint32_t next_maybe_unoccupied_index = 0;
2203
2204 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
2205 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
2206 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
2207 AstNode *tag_value = field_node->data.struct_field.value;
2208
2209 if (tag_value == nullptr) {
2210 if (occupied_tag_values.size() == 0) {
2211 bigint_init_unsigned(&type_enum_field->value, next_maybe_unoccupied_index);
2212 next_maybe_unoccupied_index += 1;
2213 } else {
2214 BigInt proposed_value;
2215 for (;;) {
2216 bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index);
2217 next_maybe_unoccupied_index += 1;
2218 auto entry = occupied_tag_values.put_unique(proposed_value, field_node);
2219 if (entry != nullptr) {
2220 continue;
2221 }
2222 break;
2223 }
2224 bigint_init_bigint(&type_enum_field->value, &proposed_value);
2225 }
2226 }
2227 }
2228
2158 enum_type->data.enumeration.zero_bits_loop_flag = false;2229 enum_type->data.enumeration.zero_bits_loop_flag = false;
2159 enum_type->data.enumeration.gen_field_count = gen_field_index;2230 enum_type->data.enumeration.gen_field_count = gen_field_index;
2160 enum_type->zero_bits = (gen_field_index == 0 && field_count < 2);2231 enum_type->zero_bits = (gen_field_index == 0 && field_count < 2);
...@@ -2162,7 +2233,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {...@@ -2162,7 +2233,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
21622233
2163 // also compute abi_alignment2234 // also compute abi_alignment
2164 if (!enum_type->zero_bits) {2235 if (!enum_type->zero_bits) {
2165 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count);
2166 uint32_t align_of_tag_in_bytes = LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);2236 uint32_t align_of_tag_in_bytes = LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);
2167 enum_type->data.enumeration.abi_alignment = max(align_of_tag_in_bytes, biggest_align_bytes);2237 enum_type->data.enumeration.abi_alignment = max(align_of_tag_in_bytes, biggest_align_bytes);
2168 }2238 }
...@@ -2214,6 +2284,11 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {...@@ -2214,6 +2284,11 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {
2214 type_struct_field->src_index = i;2284 type_struct_field->src_index = i;
2215 type_struct_field->gen_index = SIZE_MAX;2285 type_struct_field->gen_index = SIZE_MAX;
22162286
2287 if (field_node->data.struct_field.value != nullptr) {
2288 add_node_error(g, field_node->data.struct_field.value,
2289 buf_sprintf("enums, not structs, support field assignment"));
2290 }
2291
2217 type_ensure_zero_bits_known(g, field_type);2292 type_ensure_zero_bits_known(g, field_type);
2218 if (type_is_invalid(field_type)) {2293 if (type_is_invalid(field_type)) {
2219 struct_type->data.structure.is_invalid = true;2294 struct_type->data.structure.is_invalid = true;
...@@ -2277,7 +2352,14 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {...@@ -2277,7 +2352,14 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
2277 type_union_field->name = field_node->data.struct_field.name;2352 type_union_field->name = field_node->data.struct_field.name;
2278 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);2353 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
2279 type_union_field->type_entry = field_type;2354 type_union_field->type_entry = field_type;
2280 type_union_field->value = i;2355
2356 // TODO look for enum arg to union
2357 bigint_init_unsigned(&type_union_field->value, i);
2358
2359 if (field_node->data.struct_field.value != nullptr) {
2360 add_node_error(g, field_node->data.struct_field.value,
2361 buf_sprintf("enums, not unions, support field assignment"));
2362 }
22812363
2282 type_ensure_zero_bits_known(g, field_type);2364 type_ensure_zero_bits_known(g, field_type);
2283 if (type_is_invalid(field_type)) {2365 if (type_is_invalid(field_type)) {
...@@ -3190,6 +3272,29 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) {...@@ -3190,6 +3272,29 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) {
3190 return nullptr;3272 return nullptr;
3191}3273}
31923274
3275static TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) {
3276 assert(type_entry->id == TypeTableEntryIdUnion);
3277 assert(type_entry->data.unionation.complete);
3278 for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {
3279 TypeUnionField *field = &type_entry->data.unionation.fields[i];
3280 if (bigint_cmp(&field->value, tag) == CmpEQ) {
3281 return field;
3282 }
3283 }
3284 return nullptr;
3285}
3286
3287TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag) {
3288 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
3289 TypeEnumField *field = &enum_type->data.enumeration.fields[i];
3290 if (bigint_cmp(&field->value, tag) == CmpEQ) {
3291 return field;
3292 }
3293 }
3294 return nullptr;
3295}
3296
3297
3193static bool is_container(TypeTableEntry *type_entry) {3298static bool is_container(TypeTableEntry *type_entry) {
3194 switch (type_entry->id) {3299 switch (type_entry->id) {
3195 case TypeTableEntryIdInvalid:3300 case TypeTableEntryIdInvalid:
...@@ -4178,6 +4283,18 @@ ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {...@@ -4178,6 +4283,18 @@ ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {
4178 return const_val;4283 return const_val;
4179}4284}
41804285
4286void init_const_bigint(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *bigint) {
4287 const_val->special = ConstValSpecialStatic;
4288 const_val->type = type;
4289 bigint_init_bigint(&const_val->data.x_bigint, bigint);
4290}
4291
4292ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint) {
4293 ConstExprValue *const_val = create_const_vals(1);
4294 init_const_bigint(const_val, type, bigint);
4295 return const_val;
4296}
4297
4181void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) {4298void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) {
4182 const_val->special = ConstValSpecialStatic;4299 const_val->special = ConstValSpecialStatic;
4183 const_val->type = type;4300 const_val->type = type;
...@@ -4241,13 +4358,13 @@ ConstExprValue *create_const_float(TypeTableEntry *type, double value) {...@@ -4241,13 +4358,13 @@ ConstExprValue *create_const_float(TypeTableEntry *type, double value) {
4241 return const_val;4358 return const_val;
4242}4359}
42434360
4244void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, uint64_t tag) {4361void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag) {
4245 const_val->special = ConstValSpecialStatic;4362 const_val->special = ConstValSpecialStatic;
4246 const_val->type = type;4363 const_val->type = type;
4247 const_val->data.x_enum.tag = tag;4364 bigint_init_bigint(&const_val->data.x_enum.tag, tag);
4248}4365}
42494366
4250ConstExprValue *create_const_enum_tag(TypeTableEntry *type, uint64_t tag) {4367ConstExprValue *create_const_enum_tag(TypeTableEntry *type, const BigInt *tag) {
4251 ConstExprValue *const_val = create_const_vals(1);4368 ConstExprValue *const_val = create_const_vals(1);
4252 init_const_enum_tag(const_val, type, tag);4369 init_const_enum_tag(const_val, type, tag);
4253 return const_val;4370 return const_val;
...@@ -4450,20 +4567,35 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {...@@ -4450,20 +4567,35 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
4450 switch (a->type->id) {4567 switch (a->type->id) {
4451 case TypeTableEntryIdOpaque:4568 case TypeTableEntryIdOpaque:
4452 zig_unreachable();4569 zig_unreachable();
4453 case TypeTableEntryIdEnum:4570 case TypeTableEntryIdEnum: {
4454 {4571 ConstEnumValue *enum1 = &a->data.x_enum;
4455 ConstEnumValue *enum1 = &a->data.x_enum;4572 ConstEnumValue *enum2 = &b->data.x_enum;
4456 ConstEnumValue *enum2 = &b->data.x_enum;4573 if (bigint_cmp(&enum1->tag, &enum2->tag) == CmpEQ) {
4457 if (enum1->tag == enum2->tag) {4574 TypeEnumField *field = find_enum_field_by_tag(a->type, &enum1->tag);
4458 TypeEnumField *enum_field = &a->type->data.enumeration.fields[enum1->tag];4575 assert(field != nullptr);
4459 if (type_has_bits(enum_field->type_entry)) {4576 if (type_has_bits(field->type_entry)) {
4460 zig_panic("TODO const expr analyze enum special value for equality");4577 zig_panic("TODO const expr analyze enum field value for equality");
4461 } else {4578 } else {
4462 return true;4579 return true;
4463 }
4464 }4580 }
4465 return false;
4466 }4581 }
4582 return false;
4583 }
4584 case TypeTableEntryIdUnion: {
4585 ConstUnionValue *union1 = &a->data.x_union;
4586 ConstUnionValue *union2 = &b->data.x_union;
4587
4588 if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) {
4589 TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag);
4590 assert(field != nullptr);
4591 if (type_has_bits(field->type_entry)) {
4592 zig_panic("TODO const expr analyze union field value for equality");
4593 } else {
4594 return true;
4595 }
4596 }
4597 return false;
4598 }
4467 case TypeTableEntryIdMetaType:4599 case TypeTableEntryIdMetaType:
4468 return a->data.x_type == b->data.x_type;4600 return a->data.x_type == b->data.x_type;
4469 case TypeTableEntryIdVoid:4601 case TypeTableEntryIdVoid:
...@@ -4544,8 +4676,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {...@@ -4544,8 +4676,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
4544 return false;4676 return false;
4545 }4677 }
4546 return true;4678 return true;
4547 case TypeTableEntryIdUnion:
4548 zig_panic("TODO");
4549 case TypeTableEntryIdUndefLit:4679 case TypeTableEntryIdUndefLit:
4550 zig_panic("TODO");4680 zig_panic("TODO");
4551 case TypeTableEntryIdNullLit:4681 case TypeTableEntryIdNullLit:
...@@ -4855,11 +4985,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -4855,11 +4985,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
4855}4985}
48564986
4857TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {4987TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
4858 assert(size_in_bits > 0);
4859
4860 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);4988 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
4861 entry->is_copyable = true;4989 entry->is_copyable = true;
4862 entry->type_ref = LLVMIntType(size_in_bits);4990 entry->type_ref = (size_in_bits == 0) ? LLVMVoidType() : LLVMIntType(size_in_bits);
4991 entry->zero_bits = (size_in_bits == 0);
48634992
4864 const char u_or_i = is_signed ? 'i' : 'u';4993 const char u_or_i = is_signed ? 'i' : 'u';
4865 buf_resize(&entry->name, 0);4994 buf_resize(&entry->name, 0);
...@@ -4880,7 +5009,8 @@ TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits)...@@ -4880,7 +5009,8 @@ TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits)
4880 }5009 }
4881 }5010 }
48825011
4883 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);5012 uint64_t debug_size_in_bits = (size_in_bits == 0) ?
5013 0 : (8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref));
4884 entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), debug_size_in_bits, dwarf_tag);5014 entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), debug_size_in_bits, dwarf_tag);
4885 entry->data.integral.is_signed = is_signed;5015 entry->data.integral.is_signed = is_signed;
4886 entry->data.integral.bit_count = size_in_bits;5016 entry->data.integral.bit_count = size_in_bits;
src/analyze.hpp+7-2
...@@ -64,6 +64,8 @@ TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);...@@ -64,6 +64,8 @@ TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);
64ScopeDecls *get_container_scope(TypeTableEntry *type_entry);64ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
65TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);65TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
66TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);66TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);
67TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag);
68
67bool is_container_ref(TypeTableEntry *type_entry);69bool is_container_ref(TypeTableEntry *type_entry);
68void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);70void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
69void scan_import(CodeGen *g, ImportTableEntry *import);71void scan_import(CodeGen *g, ImportTableEntry *import);
...@@ -109,6 +111,9 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);...@@ -109,6 +111,9 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
109void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str);111void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str);
110ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str);112ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str);
111113
114void init_const_bigint(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *bigint);
115ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint);
116
112void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative);117void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative);
113ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative);118ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative);
114119
...@@ -121,8 +126,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x);...@@ -121,8 +126,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x);
121void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value);126void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value);
122ConstExprValue *create_const_float(TypeTableEntry *type, double value);127ConstExprValue *create_const_float(TypeTableEntry *type, double value);
123128
124void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, uint64_t tag);129void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag);
125ConstExprValue *create_const_enum_tag(TypeTableEntry *type, uint64_t tag);130ConstExprValue *create_const_enum_tag(TypeTableEntry *type, const BigInt *tag);
126131
127void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value);132void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value);
128ConstExprValue *create_const_bool(CodeGen *g, bool value);133ConstExprValue *create_const_bool(CodeGen *g, bool value);
src/ast_render.cpp+4
...@@ -677,6 +677,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -677,6 +677,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
677 fprintf(ar->f, ": ");677 fprintf(ar->f, ": ");
678 render_node_grouped(ar, field_node->data.struct_field.type);678 render_node_grouped(ar, field_node->data.struct_field.type);
679 }679 }
680 if (field_node->data.struct_field.value != nullptr) {
681 fprintf(ar->f, "= ");
682 render_node_grouped(ar, field_node->data.struct_field.value);
683 }
680 fprintf(ar->f, ",\n");684 fprintf(ar->f, ",\n");
681 }685 }
682686
src/bigint.cpp+32
...@@ -1224,3 +1224,35 @@ Cmp bigint_cmp_zero(const BigInt *op) {...@@ -1224,3 +1224,35 @@ Cmp bigint_cmp_zero(const BigInt *op) {
1224 }1224 }
1225 return op->is_negative ? CmpLT : CmpGT;1225 return op->is_negative ? CmpLT : CmpGT;
1226}1226}
1227
1228uint32_t bigint_hash(BigInt x) {
1229 if (x.digit_count == 0) {
1230 return 0;
1231 } else {
1232 return bigint_ptr(&x)[0];
1233 }
1234}
1235
1236bool bigint_eql(BigInt a, BigInt b) {
1237 return bigint_cmp(&a, &b) == CmpEQ;
1238}
1239
1240void bigint_incr(BigInt *x) {
1241 if (x->digit_count == 0) {
1242 bigint_init_unsigned(x, 1);
1243 return;
1244 }
1245
1246 if (x->digit_count == 1 && x->data.digit != UINT64_MAX) {
1247 x->data.digit += 1;
1248 return;
1249 }
1250
1251 BigInt copy;
1252 bigint_init_bigint(&copy, x);
1253
1254 BigInt one;
1255 bigint_init_unsigned(&one, 1);
1256
1257 bigint_add(x, &copy, &one);
1258}
src/bigint.hpp+5
...@@ -88,6 +88,11 @@ size_t bigint_bits_needed(const BigInt *op);...@@ -88,6 +88,11 @@ size_t bigint_bits_needed(const BigInt *op);
88// convenience functions88// convenience functions
89Cmp bigint_cmp_zero(const BigInt *op);89Cmp bigint_cmp_zero(const BigInt *op);
9090
91void bigint_incr(BigInt *value);
92
91bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result);93bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result);
9294
95uint32_t bigint_hash(BigInt x);
96bool bigint_eql(BigInt a, BigInt b);
97
93#endif98#endif
src/codegen.cpp+19-12
...@@ -1362,8 +1362,12 @@ static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) {...@@ -1362,8 +1362,12 @@ static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) {
1362 if (bigint->digit_count == 0) {1362 if (bigint->digit_count == 0) {
1363 return LLVMConstNull(type_ref);1363 return LLVMConstNull(type_ref);
1364 }1364 }
1365 LLVMValueRef unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref,1365 LLVMValueRef unsigned_val;
1366 bigint->digit_count, bigint_ptr(bigint));1366 if (bigint->digit_count == 1) {
1367 unsigned_val = LLVMConstInt(type_ref, bigint_ptr(bigint)[0], false);
1368 } else {
1369 unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref, bigint->digit_count, bigint_ptr(bigint));
1370 }
1367 if (bigint->is_negative) {1371 if (bigint->is_negative) {
1368 return LLVMConstNeg(unsigned_val);1372 return LLVMConstNeg(unsigned_val);
1369 } else {1373 } else {
...@@ -2420,9 +2424,10 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab...@@ -2420,9 +2424,10 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
2420 if (ir_want_debug_safety(g, &instruction->base)) {2424 if (ir_want_debug_safety(g, &instruction->base)) {
2421 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");2425 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");
2422 LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, "");2426 LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, "");
2423 LLVMValueRef expected_tag_value = LLVMConstInt(union_type->data.unionation.tag_type->type_ref,
2424 field->value, false);
24252427
2428
2429 LLVMValueRef expected_tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref,
2430 &field->value);
2426 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk");2431 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk");
2427 LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail");2432 LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail");
2428 LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, tag_value, expected_tag_value, "");2433 LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, tag_value, expected_tag_value, "");
...@@ -3364,9 +3369,9 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI...@@ -3364,9 +3369,9 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI
33643369
3365static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) {3370static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) {
3366 TypeTableEntry *enum_type = instruction->enum_type;3371 TypeTableEntry *enum_type = instruction->enum_type;
3367 uint32_t value = instruction->field->value;
3368 LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref;3372 LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref;
3369 LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, value, false);3373
3374 LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, &instruction->field->value);
33703375
3371 if (enum_type->data.enumeration.gen_field_count == 0)3376 if (enum_type->data.enumeration.gen_field_count == 0)
3372 return tag_value;3377 return tag_value;
...@@ -3429,8 +3434,9 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I...@@ -3429,8 +3434,9 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I
3429 if (union_type->data.unionation.gen_tag_index != SIZE_MAX) {3434 if (union_type->data.unionation.gen_tag_index != SIZE_MAX) {
3430 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,3435 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
3431 union_type->data.unionation.gen_tag_index, "");3436 union_type->data.unionation.gen_tag_index, "");
3432 LLVMValueRef tag_value = LLVMConstInt(union_type->data.unionation.tag_type->type_ref,3437
3433 type_union_field->value, false);3438 LLVMValueRef tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref,
3439 &type_union_field->value);
3434 gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);3440 gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
34353441
3436 uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,3442 uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
...@@ -4039,7 +4045,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -4039,7 +4045,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
4039 return union_value_ref;4045 return union_value_ref;
4040 }4046 }
40414047
4042 LLVMValueRef tag_value = LLVMConstInt(type_entry->data.unionation.tag_type->type_ref, const_val->data.x_union.tag, false);4048 LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
4049 &const_val->data.x_union.tag);
40434050
4044 LLVMValueRef fields[2];4051 LLVMValueRef fields[2];
4045 fields[type_entry->data.unionation.gen_union_index] = union_value_ref;4052 fields[type_entry->data.unionation.gen_union_index] = union_value_ref;
...@@ -4055,13 +4062,13 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -4055,13 +4062,13 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
4055 case TypeTableEntryIdEnum:4062 case TypeTableEntryIdEnum:
4056 {4063 {
4057 LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref;4064 LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref;
4058 LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, const_val->data.x_enum.tag, false);4065 LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, &const_val->data.x_enum.tag);
4059 if (type_entry->data.enumeration.gen_field_count == 0) {4066 if (type_entry->data.enumeration.gen_field_count == 0) {
4060 return tag_value;4067 return tag_value;
4061 } else {4068 } else {
4062 LLVMTypeRef union_type_ref = type_entry->data.enumeration.union_type_ref;4069 LLVMTypeRef union_type_ref = type_entry->data.enumeration.union_type_ref;
4063 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag];4070 TypeEnumField *enum_field = find_enum_field_by_tag(type_entry, &const_val->data.x_enum.tag);
4064 assert(enum_field->value == const_val->data.x_enum.tag);4071 assert(bigint_cmp(&enum_field->value, &const_val->data.x_enum.tag) == CmpEQ);
4065 LLVMValueRef union_value;4072 LLVMValueRef union_value;
40664073
4067 bool make_unnamed_struct;4074 bool make_unnamed_struct;
src/ir.cpp+66-43
...@@ -8387,7 +8387,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -8387,7 +8387,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
8387 return ira->codegen->invalid_instruction;8387 return ira->codegen->invalid_instruction;
8388 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,8388 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
8389 source_instr->source_node, wanted_type);8389 source_instr->source_node, wanted_type);
8390 init_const_unsigned_negative(&result->value, wanted_type, val->data.x_enum.tag, false);8390 init_const_bigint(&result->value, wanted_type, &val->data.x_enum.tag);
8391 return result;8391 return result;
8392 }8392 }
83938393
...@@ -8469,7 +8469,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -8469,7 +8469,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
84698469
8470 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,8470 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
8471 source_instr->source_node, wanted_type);8471 source_instr->source_node, wanted_type);
8472 result->value.data.x_enum.tag = bigint_as_unsigned(&val->data.x_bigint);8472 bigint_init_bigint(&result->value.data.x_enum.tag, &val->data.x_bigint);
8473 return result;8473 return result;
8474 }8474 }
84758475
...@@ -9148,7 +9148,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic...@@ -9148,7 +9148,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic
9148 if (!const_val)9148 if (!const_val)
9149 return false;9149 return false;
91509150
9151 *out = (AtomicOrder)const_val->data.x_enum.tag;9151 *out = (AtomicOrder)bigint_as_unsigned(&const_val->data.x_enum.tag);
9152 return true;9152 return true;
9153}9153}
91549154
...@@ -9168,7 +9168,27 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob...@@ -9168,7 +9168,27 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob
9168 if (!const_val)9168 if (!const_val)
9169 return false;9169 return false;
91709170
9171 *out = (GlobalLinkageId)const_val->data.x_enum.tag;9171 *out = (GlobalLinkageId)bigint_as_unsigned(&const_val->data.x_enum.tag);
9172 return true;
9173}
9174
9175static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMode *out) {
9176 if (type_is_invalid(value->value.type))
9177 return false;
9178
9179 ConstExprValue *float_mode_val = get_builtin_value(ira->codegen, "FloatMode");
9180 assert(float_mode_val->type->id == TypeTableEntryIdMetaType);
9181 TypeTableEntry *float_mode_type = float_mode_val->data.x_type;
9182
9183 IrInstruction *casted_value = ir_implicit_cast(ira, value, float_mode_type);
9184 if (type_is_invalid(casted_value->value.type))
9185 return false;
9186
9187 ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
9188 if (!const_val)
9189 return false;
9190
9191 *out = (FloatMode)bigint_as_unsigned(&const_val->data.x_enum.tag);
9172 return true;9192 return true;
9173}9193}
91749194
...@@ -11825,13 +11845,13 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru...@@ -11825,13 +11845,13 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
11825 bool ptr_is_const = true;11845 bool ptr_is_const = true;
11826 bool ptr_is_volatile = false;11846 bool ptr_is_volatile = false;
11827 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,11847 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11828 create_const_enum_tag(child_type, field->value), child_type,11848 create_const_enum_tag(child_type, &field->value), child_type,
11829 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);11849 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11830 } else {11850 } else {
11831 bool ptr_is_const = true;11851 bool ptr_is_const = true;
11832 bool ptr_is_volatile = false;11852 bool ptr_is_volatile = false;
11833 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,11853 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11834 create_const_unsigned_negative(child_type->data.enumeration.tag_type, field->value, false),11854 create_const_bigint(child_type->data.enumeration.tag_type, &field->value),
11835 child_type->data.enumeration.tag_type,11855 child_type->data.enumeration.tag_type,
11836 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);11856 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11837 }11857 }
...@@ -12420,21 +12440,11 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,...@@ -12420,21 +12440,11 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
12420 return ira->codegen->builtin_types.entry_invalid;12440 return ira->codegen->builtin_types.entry_invalid;
12421 }12441 }
1242212442
12423 ConstExprValue *float_mode_val = get_builtin_value(ira->codegen, "FloatMode");
12424 assert(float_mode_val->type->id == TypeTableEntryIdMetaType);
12425 TypeTableEntry *float_mode_enum_type = float_mode_val->data.x_type;
12426
12427 IrInstruction *float_mode_value = instruction->mode_value->other;12443 IrInstruction *float_mode_value = instruction->mode_value->other;
12428 if (type_is_invalid(float_mode_value->value.type))
12429 return ira->codegen->builtin_types.entry_invalid;
12430 IrInstruction *casted_value = ir_implicit_cast(ira, float_mode_value, float_mode_enum_type);
12431 if (type_is_invalid(casted_value->value.type))
12432 return ira->codegen->builtin_types.entry_invalid;
12433 ConstExprValue *mode_val = ir_resolve_const(ira, casted_value, UndefBad);
12434 if (!mode_val)
12435 return ira->codegen->builtin_types.entry_invalid;
1243612444
12437 bool want_fast_math = (mode_val->data.x_enum.tag == FloatModeOptimized);12445 FloatMode float_mode_scalar;
12446 if (!ir_resolve_float_mode(ira, float_mode_value, &float_mode_scalar))
12447 return ira->codegen->builtin_types.entry_invalid;
1243812448
12439 AstNode *source_node = instruction->base.source_node;12449 AstNode *source_node = instruction->base.source_node;
12440 if (*fast_math_set_node_ptr) {12450 if (*fast_math_set_node_ptr) {
...@@ -12444,7 +12454,7 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,...@@ -12444,7 +12454,7 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
12444 return ira->codegen->builtin_types.entry_invalid;12454 return ira->codegen->builtin_types.entry_invalid;
12445 }12455 }
12446 *fast_math_set_node_ptr = source_node;12456 *fast_math_set_node_ptr = source_node;
12447 *fast_math_off_ptr = !want_fast_math;12457 *fast_math_off_ptr = (float_mode_scalar == FloatModeStrict);
1244812458
12449 ir_build_const_from(ira, &instruction->base);12459 ir_build_const_from(ira, &instruction->base);
12450 return ira->codegen->builtin_types.entry_void;12460 return ira->codegen->builtin_types.entry_void;
...@@ -12835,7 +12845,7 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_...@@ -12835,7 +12845,7 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_
12835 source_instr->scope, source_instr->source_node);12845 source_instr->scope, source_instr->source_node);
12836 const_instruction->base.value.type = tag_type;12846 const_instruction->base.value.type = tag_type;
12837 const_instruction->base.value.special = ConstValSpecialStatic;12847 const_instruction->base.value.special = ConstValSpecialStatic;
12838 bigint_init_unsigned(&const_instruction->base.value.data.x_bigint, val->data.x_enum.tag);12848 bigint_init_bigint(&const_instruction->base.value.data.x_bigint, &val->data.x_enum.tag);
12839 return &const_instruction->base;12849 return &const_instruction->base;
12840 }12850 }
1284112851
...@@ -13005,7 +13015,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -13005,7 +13015,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
13005 assert(tag_type != nullptr);13015 assert(tag_type != nullptr);
13006 if (pointee_val) {13016 if (pointee_val) {
13007 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);13017 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
13008 bigint_init_unsigned(&out_val->data.x_bigint, pointee_val->data.x_enum.tag);13018 bigint_init_bigint(&out_val->data.x_bigint, &pointee_val->data.x_enum.tag);
13009 return tag_type;13019 return tag_type;
13010 }13020 }
1301113021
...@@ -13056,9 +13066,9 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr...@@ -13056,9 +13066,9 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
1305613066
13057 TypeEnumField *field;13067 TypeEnumField *field;
13058 if (prong_value->value.type->id == TypeTableEntryIdEnumTag) {13068 if (prong_value->value.type->id == TypeTableEntryIdEnumTag) {
13059 field = &target_type->data.enumeration.fields[bigint_as_unsigned(&prong_val->data.x_bigint)];13069 field = find_enum_field_by_tag(target_type, &prong_val->data.x_bigint);
13060 } else if (prong_value->value.type->id == TypeTableEntryIdEnum) {13070 } else if (prong_value->value.type->id == TypeTableEntryIdEnum) {
13061 field = &target_type->data.enumeration.fields[prong_val->data.x_enum.tag];13071 field = find_enum_field_by_tag(target_type, &prong_val->data.x_enum.tag);
13062 } else {13072 } else {
13063 zig_unreachable();13073 zig_unreachable();
13064 }13074 }
...@@ -13503,8 +13513,8 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira...@@ -13503,8 +13513,8 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
1350313513
13504 TypeTableEntry *enum_type = container_type_value->value.type->data.enum_tag.enum_type;13514 TypeTableEntry *enum_type = container_type_value->value.type->data.enum_tag.enum_type;
1350513515
13506 uint64_t tag_uint = bigint_as_unsigned(&tag_value->data.x_bigint);13516 TypeEnumField *field = find_enum_field_by_tag(enum_type, &tag_value->data.x_bigint);
13507 TypeEnumField *field = &enum_type->data.enumeration.fields[tag_uint];13517 assert(field != nullptr);
13508 TypeTableEntry *this_field_type = field->type_entry;13518 TypeTableEntry *this_field_type = field->type_entry;
1350913519
13510 IrInstruction *init_value = instruction->items[0]->other;13520 IrInstruction *init_value = instruction->items[0]->other;
...@@ -13520,7 +13530,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira...@@ -13520,7 +13530,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
13520 if (!init_val)13530 if (!init_val)
13521 return ira->codegen->builtin_types.entry_invalid;13531 return ira->codegen->builtin_types.entry_invalid;
13522 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);13532 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13523 out_val->data.x_enum.tag = tag_uint;13533 bigint_init_bigint(&out_val->data.x_enum.tag, &tag_value->data.x_bigint);
13524 out_val->data.x_enum.payload = init_val;13534 out_val->data.x_enum.payload = init_val;
13525 return enum_type;13535 return enum_type;
13526 }13536 }
...@@ -13859,7 +13869,7 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira,...@@ -13859,7 +13869,7 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira,
13859 TypeTableEntry *result_type = var_value->data.x_type;13869 TypeTableEntry *result_type = var_value->data.x_type;
1386013870
13861 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);13871 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13862 out_val->data.x_enum.tag = type_id_index(type_entry->id);13872 bigint_init_unsigned(&out_val->data.x_enum.tag, type_id_index(type_entry->id));
13863 return result_type;13873 return result_type;
13864}13874}
1386513875
...@@ -15117,7 +15127,9 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira...@@ -15117,7 +15127,9 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
1511715127
15118 if (switch_type->id == TypeTableEntryIdEnumTag) {15128 if (switch_type->id == TypeTableEntryIdEnumTag) {
15119 TypeTableEntry *enum_type = switch_type->data.enum_tag.enum_type;15129 TypeTableEntry *enum_type = switch_type->data.enum_tag.enum_type;
15120 AstNode **field_prev_uses = allocate<AstNode *>(enum_type->data.enumeration.src_field_count);15130 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> field_prev_uses = {};
15131 field_prev_uses.init(enum_type->data.enumeration.src_field_count);
15132
15121 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {15133 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
15122 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];15134 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
1512315135
...@@ -15129,41 +15141,52 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira...@@ -15129,41 +15141,52 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
15129 if (type_is_invalid(end_value->value.type))15141 if (type_is_invalid(end_value->value.type))
15130 return ira->codegen->builtin_types.entry_invalid;15142 return ira->codegen->builtin_types.entry_invalid;
1513115143
15132 size_t start_index;15144 BigInt start_index;
15133 size_t end_index;15145 BigInt end_index;
15134 if (start_value->value.type->id == TypeTableEntryIdEnumTag) {15146 if (start_value->value.type->id == TypeTableEntryIdEnumTag) {
15135 start_index = bigint_as_unsigned(&start_value->value.data.x_bigint);15147 bigint_init_bigint(&start_index, &start_value->value.data.x_bigint);
15136 } else if (start_value->value.type->id == TypeTableEntryIdEnum) {15148 } else if (start_value->value.type->id == TypeTableEntryIdEnum) {
15137 start_index = start_value->value.data.x_enum.tag;15149 bigint_init_bigint(&start_index, &start_value->value.data.x_enum.tag);
15138 } else {15150 } else {
15139 zig_unreachable();15151 zig_unreachable();
15140 }15152 }
15141 if (end_value->value.type->id == TypeTableEntryIdEnumTag) {15153 if (end_value->value.type->id == TypeTableEntryIdEnumTag) {
15142 end_index = bigint_as_unsigned(&end_value->value.data.x_bigint);15154 bigint_init_bigint(&end_index, &end_value->value.data.x_bigint);
15143 } else if (end_value->value.type->id == TypeTableEntryIdEnum) {15155 } else if (end_value->value.type->id == TypeTableEntryIdEnum) {
15144 end_index = end_value->value.data.x_enum.tag;15156 bigint_init_bigint(&end_index, &end_value->value.data.x_enum.tag);
15145 } else {15157 } else {
15146 zig_unreachable();15158 zig_unreachable();
15147 }15159 }
1514815160
15149 for (size_t field_index = start_index; field_index <= end_index; field_index += 1) {15161 BigInt field_index;
15150 AstNode *prev_node = field_prev_uses[field_index];15162 bigint_init_bigint(&field_index, &start_index);
15151 if (prev_node != nullptr) {15163 for (;;) {
15152 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_index];15164 Cmp cmp = bigint_cmp(&field_index, &end_index);
15165 if (cmp == CmpGT) {
15166 break;
15167 }
15168 auto entry = field_prev_uses.put_unique(field_index, start_value->source_node);
15169 if (entry) {
15170 AstNode *prev_node = entry->value;
15171 TypeEnumField *enum_field = find_enum_field_by_tag(enum_type, &field_index);
15172 assert(enum_field != nullptr);
15153 ErrorMsg *msg = ir_add_error(ira, start_value,15173 ErrorMsg *msg = ir_add_error(ira, start_value,
15154 buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&enum_type->name),15174 buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&enum_type->name),
15155 buf_ptr(type_enum_field->name)));15175 buf_ptr(enum_field->name)));
15156 add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here"));15176 add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here"));
15157 }15177 }
15158 field_prev_uses[field_index] = start_value->source_node;15178 bigint_incr(&field_index);
15159 }15179 }
15160 }15180 }
15161 if (!instruction->have_else_prong) {15181 if (!instruction->have_else_prong) {
15162 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {15182 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
15163 if (field_prev_uses[i] == nullptr) {15183 TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i];
15184
15185 auto entry = field_prev_uses.maybe_get(enum_field->value);
15186 if (!entry) {
15164 ir_add_error(ira, &instruction->base,15187 ir_add_error(ira, &instruction->base,
15165 buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&enum_type->name),15188 buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&enum_type->name),
15166 buf_ptr(enum_type->data.enumeration.fields[i].name)));15189 buf_ptr(enum_field->name)));
15167 }15190 }
15168 }15191 }
15169 }15192 }
src/parser.cpp+25-23
...@@ -2379,7 +2379,7 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi...@@ -2379,7 +2379,7 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi
2379/*2379/*
2380ContainerDecl = option("extern" | "packed") ("struct" | "union" | ("enum" option(GroupedExpression))) "{" many(ContainerMember) "}"2380ContainerDecl = option("extern" | "packed") ("struct" | "union" | ("enum" option(GroupedExpression))) "{" many(ContainerMember) "}"
2381ContainerMember = (ContainerField | FnDef | GlobalVarDecl)2381ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
2382ContainerField = Symbol option(":" Expression) ","2382ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression ","
2383*/2383*/
2384static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) {2384static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) {
2385 Token *first_token = &pc->tokens->at(*token_index);2385 Token *first_token = &pc->tokens->at(*token_index);
...@@ -2414,10 +2414,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2414,10 +2414,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2414 AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token);2414 AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token);
2415 node->data.container_decl.layout = layout;2415 node->data.container_decl.layout = layout;
2416 node->data.container_decl.kind = kind;2416 node->data.container_decl.kind = kind;
24172417 node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, false);
2418 if (kind == ContainerKindEnum || kind == ContainerKindStruct) {
2419 node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, false);
2420 }
24212418
2422 ast_eat_token(pc, token_index, TokenIdLBrace);2419 ast_eat_token(pc, token_index, TokenIdLBrace);
24232420
...@@ -2456,31 +2453,35 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2456,31 +2453,35 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2456 AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token);2453 AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token);
2457 *token_index += 1;2454 *token_index += 1;
24582455
2456 node->data.container_decl.fields.append(field_node);
2459 field_node->data.struct_field.visib_mod = visib_mod;2457 field_node->data.struct_field.visib_mod = visib_mod;
2460 field_node->data.struct_field.name = token_buf(token);2458 field_node->data.struct_field.name = token_buf(token);
24612459
2462 Token *token = &pc->tokens->at(*token_index);2460 Token *colon_token = &pc->tokens->at(*token_index);
2463 if (token->id == TokenIdComma || token->id == TokenIdRBrace) {2461 if (colon_token->id == TokenIdColon) {
2464 field_node->data.struct_field.type = ast_create_void_type_node(pc, token);
2465 *token_index += 1;2462 *token_index += 1;
2466 node->data.container_decl.fields.append(field_node);2463 field_node->data.struct_field.type = ast_parse_prefix_op_expr(pc, token_index, true);
2467
2468 if (token->id == TokenIdRBrace) {
2469 break;
2470 }
2471 } else {2464 } else {
2472 ast_eat_token(pc, token_index, TokenIdColon);2465 field_node->data.struct_field.type = ast_create_void_type_node(pc, colon_token);
2473 field_node->data.struct_field.type = ast_parse_expression(pc, token_index, true);2466 }
2474 node->data.container_decl.fields.append(field_node);2467 Token *eq_token = &pc->tokens->at(*token_index);
2468 if (eq_token->id == TokenIdEq) {
2469 *token_index += 1;
2470 field_node->data.struct_field.value = ast_parse_prefix_op_expr(pc, token_index, true);
2471 }
24752472
2476 Token *token = &pc->tokens->at(*token_index);2473 Token *next_token = &pc->tokens->at(*token_index);
2477 if (token->id == TokenIdRBrace) {2474 if (next_token->id == TokenIdComma) {
2478 *token_index += 1;2475 *token_index += 1;
2479 break;2476 continue;
2480 } else {
2481 ast_eat_token(pc, token_index, TokenIdComma);
2482 }
2483 }2477 }
2478
2479 if (next_token->id == TokenIdRBrace) {
2480 *token_index += 1;
2481 break;
2482 }
2483
2484 ast_invalid_token_error(pc, next_token);
2484 } else {2485 } else {
2485 ast_invalid_token_error(pc, token);2486 ast_invalid_token_error(pc, token);
2486 }2487 }
...@@ -2812,6 +2813,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2812,6 +2813,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2812 break;2813 break;
2813 case NodeTypeStructField:2814 case NodeTypeStructField:
2814 visit_field(&node->data.struct_field.type, visit, context);2815 visit_field(&node->data.struct_field.type, visit, context);
2816 visit_field(&node->data.struct_field.value, visit, context);
2815 break;2817 break;
2816 case NodeTypeContainerInitExpr:2818 case NodeTypeContainerInitExpr:
2817 visit_field(&node->data.container_init_expr.type, visit, context);2819 visit_field(&node->data.container_init_expr.type, visit, context);
std/sort.zig+1-1
...@@ -16,7 +16,7 @@ pub fn sort_stable(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b...@@ -16,7 +16,7 @@ pub fn sort_stable(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b
16 }}16 }}
17}17}
1818
19/// Unstable sort using O(n) stack space. Currentl implemented as quicksort.19/// Unstable sort using O(n) stack space. Currently implemented as quicksort.
20pub fn sort(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) {20pub fn sort(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) {
21 if (array.len > 0) {21 if (array.len > 0) {
22 quicksort(T, array, 0, array.len - 1, cmp);22 quicksort(T, array, 0, array.len - 1, cmp);
test/cases/enum.zig+54-2
...@@ -137,7 +137,6 @@ const AlignTestEnum = enum {...@@ -137,7 +137,6 @@ const AlignTestEnum = enum {
137 B: u64,137 B: u64,
138};138};
139139
140const ValueCount0 = enum {};
141const ValueCount1 = enum { I0 };140const ValueCount1 = enum { I0 };
142const ValueCount2 = enum { I0, I1 };141const ValueCount2 = enum { I0, I1 };
143const ValueCount256 = enum {142const ValueCount256 = enum {
...@@ -183,7 +182,6 @@ const ValueCount257 = enum {...@@ -183,7 +182,6 @@ const ValueCount257 = enum {
183182
184test "enum sizes" {183test "enum sizes" {
185 comptime {184 comptime {
186 assert(@sizeOf(ValueCount0) == 0);
187 assert(@sizeOf(ValueCount1) == 0);185 assert(@sizeOf(ValueCount1) == 0);
188 assert(@sizeOf(ValueCount2) == 1);186 assert(@sizeOf(ValueCount2) == 1);
189 assert(@sizeOf(ValueCount256) == 1);187 assert(@sizeOf(ValueCount256) == 1);
...@@ -292,3 +290,57 @@ test "casting enum to its tag type" {...@@ -292,3 +290,57 @@ test "casting enum to its tag type" {
292fn testCastEnumToTagType(value: Small2) {290fn testCastEnumToTagType(value: Small2) {
293 assert(u2(value) == 1);291 assert(u2(value) == 1);
294}292}
293
294const MultipleChoice = enum(u32) {
295 A = 20,
296 B = 40,
297 C = 60,
298 D = 1000,
299};
300
301test "enum with specified tag values" {
302 testEnumWithSpecifiedTagValues(MultipleChoice.C);
303 comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
304}
305
306fn testEnumWithSpecifiedTagValues(x: MultipleChoice) {
307 assert(u32(x) == 60);
308 assert(1234 == switch (x) {
309 MultipleChoice.A => 1,
310 MultipleChoice.B => 2,
311 MultipleChoice.C => u32(1234),
312 MultipleChoice.D => 4,
313 });
314}
315
316const MultipleChoice2 = enum(u32) {
317 Unspecified1,
318 A = 20,
319 Unspecified2,
320 B = 40,
321 Unspecified3,
322 C = 60,
323 Unspecified4,
324 D = 1000,
325 Unspecified5,
326};
327
328test "enum with specified and unspecified tag values" {
329 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
330 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
331}
332
333fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) {
334 assert(u32(x) == 1000);
335 assert(1234 == switch (x) {
336 MultipleChoice2.A => 1,
337 MultipleChoice2.B => 2,
338 MultipleChoice2.C => 3,
339 MultipleChoice2.D => u32(1234),
340 MultipleChoice2.Unspecified1 => 5,
341 MultipleChoice2.Unspecified2 => 6,
342 MultipleChoice2.Unspecified3 => 7,
343 MultipleChoice2.Unspecified4 => 8,
344 MultipleChoice2.Unspecified5 => 9,
345 });
346}
test/compile_errors.zig+49-6
...@@ -2307,11 +2307,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2307,11 +2307,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
23072307
2308 cases.add("@memberType enum out of bounds",2308 cases.add("@memberType enum out of bounds",
2309 \\comptime {2309 \\comptime {
2310 \\ _ = @memberType(Foo, 0);2310 \\ _ = @memberType(Foo, 1);
2311 \\}2311 \\}
2312 \\const Foo = enum {};2312 \\const Foo = enum {A,};
2313 ,2313 ,
2314 ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members");2314 ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members");
23152315
2316 cases.add("@memberName on unsupported type",2316 cases.add("@memberName on unsupported type",
2317 \\comptime {2317 \\comptime {
...@@ -2330,11 +2330,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2330,11 +2330,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
23302330
2331 cases.add("@memberName enum out of bounds",2331 cases.add("@memberName enum out of bounds",
2332 \\comptime {2332 \\comptime {
2333 \\ _ = @memberName(Foo, 0);2333 \\ _ = @memberName(Foo, 1);
2334 \\}2334 \\}
2335 \\const Foo = enum {};2335 \\const Foo = enum {A,};
2336 ,2336 ,
2337 ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members");2337 ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members");
23382338
2339 cases.add("calling var args extern function, passing array instead of pointer",2339 cases.add("calling var args extern function, passing array instead of pointer",
2340 \\export fn entry() {2340 \\export fn entry() {
...@@ -2447,4 +2447,47 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2447,4 +2447,47 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
2447 \\}2447 \\}
2448 ,2448 ,
2449 ".tmp_source.zig:1:19: error: expected unsigned integer, found 'i2'");2449 ".tmp_source.zig:1:19: error: expected unsigned integer, found 'i2'");
2450
2451 cases.add("struct fields with value assignments",
2452 \\const MultipleChoice = struct {
2453 \\ A: i32 = 20,
2454 \\};
2455 \\export fn entry() {
2456 \\ var x: MultipleChoice = undefined;
2457 \\}
2458 ,
2459 ".tmp_source.zig:2:14: error: enums, not structs, support field assignment");
2460
2461 cases.add("union fields with value assignments",
2462 \\const MultipleChoice = union {
2463 \\ A: i32 = 20,
2464 \\};
2465 \\export fn entry() {
2466 \\ var x: MultipleChoice = undefined;
2467 \\}
2468 ,
2469 ".tmp_source.zig:2:14: error: enums, not unions, support field assignment");
2470
2471 cases.add("enum with 0 fields",
2472 \\const Foo = enum {};
2473 \\export fn entry() -> usize {
2474 \\ return @sizeOf(Foo);
2475 \\}
2476 ,
2477 ".tmp_source.zig:1:13: error: enums must have 1 or more fields");
2478
2479 cases.add("enum value already taken",
2480 \\const MultipleChoice = enum(u32) {
2481 \\ A = 20,
2482 \\ B = 40,
2483 \\ C = 60,
2484 \\ D = 1000,
2485 \\ E = 60,
2486 \\};
2487 \\export fn entry() {
2488 \\ var x = MultipleChoice.C;
2489 \\}
2490 ,
2491 ".tmp_source.zig:6:9: error: enum tag value 60 already taken",
2492 ".tmp_source.zig:4:9: note: other occurrence here");
2450}2493}