authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-30 21:46:02-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-30 22:08:11-05:00
logb62e2fd8703129fcf0dc80675800f005e84ee724
treec70341d5db1c79901ce58d86c1aa24f5c972d57d
parent5786df933d37d52d57fef9c28acb9c2c23128d31

ability to specify tag type of enums

see #305

11 files changed, 180 insertions(+), 6 deletions(-)

doc/langref.html.in+7-1
...@@ -137,6 +137,7 @@...@@ -137,6 +137,7 @@
137 <li><a href="#builtin-divTrunc">@divTrunc</a></li>137 <li><a href="#builtin-divTrunc">@divTrunc</a></li>
138 <li><a href="#builtin-embedFile">@embedFile</a></li>138 <li><a href="#builtin-embedFile">@embedFile</a></li>
139 <li><a href="#builtin-enumTagName">@enumTagName</a></li>139 <li><a href="#builtin-enumTagName">@enumTagName</a></li>
140 <li><a href="#builtin-EnumTagType">@EnumTagType</a></li>
140 <li><a href="#builtin-errorName">@errorName</a></li>141 <li><a href="#builtin-errorName">@errorName</a></li>
141 <li><a href="#builtin-fence">@fence</a></li>142 <li><a href="#builtin-fence">@fence</a></li>
142 <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li>143 <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li>
...@@ -4256,6 +4257,11 @@ test.zig:6:2: error: found compile log statement...@@ -4256,6 +4257,11 @@ test.zig:6:2: error: found compile log statement
4256 <p>4257 <p>
4257 Converts an enum tag name to a slice of bytes.4258 Converts an enum tag name to a slice of bytes.
4258 </p>4259 </p>
4260 <h3 id="builtin-EnumTagType">@EnumTagType</h3>
4261 <pre><code class="zig">@EnumTagType(T: type) -&gt; type</code></pre>
4262 <p>
4263 Returns the integer type that is used to store the enumeration value.
4264 </p>
4259 <h3 id="builtin-errorName">@errorName</h3>4265 <h3 id="builtin-errorName">@errorName</h3>
4260 <pre><code class="zig">@errorName(err: error) -&gt; []u8</code></pre>4266 <pre><code class="zig">@errorName(err: error) -&gt; []u8</code></pre>
4261 <p>4267 <p>
...@@ -5837,7 +5843,7 @@ GroupedExpression = "(" Expression ")"...@@ -5837,7 +5843,7 @@ GroupedExpression = "(" Expression ")"
58375843
5838KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"5844KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"
58395845
5840ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"</code></pre>5846ContainerDecl = option("extern" | "packed") ("struct" | "union" | ("enum" option(GroupedExpression))) "{" many(ContainerMember) "}"</code></pre>
5841 <h2 id="zen">Zen</h2>5847 <h2 id="zen">Zen</h2>
5842 <ul>5848 <ul>
5843 <li>Communicate intent precisely.</li>5849 <li>Communicate intent precisely.</li>
src/all_types.hpp+8
...@@ -1286,6 +1286,7 @@ enum BuiltinFnId {...@@ -1286,6 +1286,7 @@ enum BuiltinFnId {
1286 BuiltinFnIdIntToPtr,1286 BuiltinFnIdIntToPtr,
1287 BuiltinFnIdPtrToInt,1287 BuiltinFnIdPtrToInt,
1288 BuiltinFnIdEnumTagName,1288 BuiltinFnIdEnumTagName,
1289 BuiltinFnIdEnumTagType,
1289 BuiltinFnIdFieldParentPtr,1290 BuiltinFnIdFieldParentPtr,
1290 BuiltinFnIdOffsetOf,1291 BuiltinFnIdOffsetOf,
1291 BuiltinFnIdInlineCall,1292 BuiltinFnIdInlineCall,
...@@ -1911,6 +1912,7 @@ enum IrInstructionId {...@@ -1911,6 +1912,7 @@ enum IrInstructionId {
1911 IrInstructionIdDeclRef,1912 IrInstructionIdDeclRef,
1912 IrInstructionIdPanic,1913 IrInstructionIdPanic,
1913 IrInstructionIdEnumTagName,1914 IrInstructionIdEnumTagName,
1915 IrInstructionIdEnumTagType,
1914 IrInstructionIdFieldParentPtr,1916 IrInstructionIdFieldParentPtr,
1915 IrInstructionIdOffsetOf,1917 IrInstructionIdOffsetOf,
1916 IrInstructionIdTypeId,1918 IrInstructionIdTypeId,
...@@ -2695,6 +2697,12 @@ struct IrInstructionEnumTagName {...@@ -2695,6 +2697,12 @@ struct IrInstructionEnumTagName {
2695 IrInstruction *target;2697 IrInstruction *target;
2696};2698};
26972699
2700struct IrInstructionEnumTagType {
2701 IrInstruction base;
2702
2703 IrInstruction *target;
2704};
2705
2698struct IrInstructionFieldParentPtr {2706struct IrInstructionFieldParentPtr {
2699 IrInstruction base;2707 IrInstruction base;
27002708
src/analyze.cpp+20-1
...@@ -1267,7 +1267,7 @@ TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, Type...@@ -1267,7 +1267,7 @@ TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, Type
1267 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnumTag);1267 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnumTag);
12681268
1269 buf_resize(&entry->name, 0);1269 buf_resize(&entry->name, 0);
1270 buf_appendf(&entry->name, "@enumTagType(%s)", buf_ptr(&enum_type->name));1270 buf_appendf(&entry->name, "@EnumTagType(%s)", buf_ptr(&enum_type->name));
12711271
1272 entry->is_copyable = true;1272 entry->is_copyable = true;
1273 entry->data.enum_tag.enum_type = enum_type;1273 entry->data.enum_tag.enum_type = enum_type;
...@@ -1391,6 +1391,25 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {...@@ -1391,6 +1391,25 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1391 }1391 }
13921392
1393 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);1393 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
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.bit_count < tag_int_type->data.integral.bit_count) {
1403 enum_type->data.enumeration.is_invalid = true;
1404 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
1405 buf_sprintf("'%s' too small to hold all bits; must be at least '%s'",
1406 buf_ptr(&wanted_tag_int_type->name), buf_ptr(&tag_int_type->name)));
1407 } else {
1408 tag_int_type = wanted_tag_int_type;
1409 }
1410 }
1411
1412
1394 TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type);1413 TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type);
1395 enum_type->data.enumeration.tag_type = tag_type_entry;1414 enum_type->data.enumeration.tag_type = tag_type_entry;
13961415
src/ast_render.cpp+7-1
...@@ -660,7 +660,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -660,7 +660,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
660 {660 {
661 const char *layout_str = layout_string(node->data.container_decl.layout);661 const char *layout_str = layout_string(node->data.container_decl.layout);
662 const char *container_str = container_string(node->data.container_decl.kind);662 const char *container_str = container_string(node->data.container_decl.kind);
663 fprintf(ar->f, "%s%s {\n", layout_str, container_str);663 fprintf(ar->f, "%s%s", layout_str, container_str);
664 if (node->data.container_decl.init_arg_expr != nullptr) {
665 fprintf(ar->f, "(");
666 render_node_grouped(ar, node->data.container_decl.init_arg_expr);
667 fprintf(ar->f, ")");
668 }
669 fprintf(ar->f, " {\n");
664 ar->indent += ar->indent_size;670 ar->indent += ar->indent_size;
665 for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) {671 for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) {
666 AstNode *field_node = node->data.container_decl.fields.at(field_i);672 AstNode *field_node = node->data.container_decl.fields.at(field_i);
src/codegen.cpp+3-1
...@@ -3537,6 +3537,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -3537,6 +3537,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
3537 case IrInstructionIdOpaqueType:3537 case IrInstructionIdOpaqueType:
3538 case IrInstructionIdSetAlignStack:3538 case IrInstructionIdSetAlignStack:
3539 case IrInstructionIdArgType:3539 case IrInstructionIdArgType:
3540 case IrInstructionIdEnumTagType:
3540 zig_unreachable();3541 zig_unreachable();
3541 case IrInstructionIdReturn:3542 case IrInstructionIdReturn:
3542 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);3543 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
...@@ -5049,7 +5050,8 @@ static void define_builtin_fns(CodeGen *g) {...@@ -5049,7 +5050,8 @@ static void define_builtin_fns(CodeGen *g) {
5049 create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2);5050 create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2);
5050 create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2);5051 create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2);
5051 create_builtin_fn(g, BuiltinFnIdPtrToInt, "ptrToInt", 1);5052 create_builtin_fn(g, BuiltinFnIdPtrToInt, "ptrToInt", 1);
5052 create_builtin_fn(g, BuiltinFnIdEnumTagName, "enumTagName", 1);5053 create_builtin_fn(g, BuiltinFnIdEnumTagName, "enumTagName", 1); // TODO rename to memberName
5054 create_builtin_fn(g, BuiltinFnIdEnumTagType, "EnumTagType", 1);
5053 create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3);5055 create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3);
5054 create_builtin_fn(g, BuiltinFnIdOffsetOf, "offsetOf", 2);5056 create_builtin_fn(g, BuiltinFnIdOffsetOf, "offsetOf", 2);
5055 create_builtin_fn(g, BuiltinFnIdDivExact, "divExact", 2);5057 create_builtin_fn(g, BuiltinFnIdDivExact, "divExact", 2);
src/ir.cpp+57
...@@ -551,6 +551,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTagName *) {...@@ -551,6 +551,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTagName *) {
551 return IrInstructionIdEnumTagName;551 return IrInstructionIdEnumTagName;
552}552}
553553
554static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTagType *) {
555 return IrInstructionIdEnumTagType;
556}
557
554static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldParentPtr *) {558static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldParentPtr *) {
555 return IrInstructionIdFieldParentPtr;559 return IrInstructionIdFieldParentPtr;
556}560}
...@@ -2270,6 +2274,17 @@ static IrInstruction *ir_build_enum_tag_name(IrBuilder *irb, Scope *scope, AstNo...@@ -2270,6 +2274,17 @@ static IrInstruction *ir_build_enum_tag_name(IrBuilder *irb, Scope *scope, AstNo
2270 return &instruction->base;2274 return &instruction->base;
2271}2275}
22722276
2277static IrInstruction *ir_build_enum_tag_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
2278 IrInstruction *target)
2279{
2280 IrInstructionEnumTagType *instruction = ir_build_instruction<IrInstructionEnumTagType>(irb, scope, source_node);
2281 instruction->target = target;
2282
2283 ir_ref_instruction(target, irb->current_basic_block);
2284
2285 return &instruction->base;
2286}
2287
2273static IrInstruction *ir_build_field_parent_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,2288static IrInstruction *ir_build_field_parent_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
2274 IrInstruction *type_value, IrInstruction *field_name, IrInstruction *field_ptr, TypeStructField *field)2289 IrInstruction *type_value, IrInstruction *field_name, IrInstruction *field_ptr, TypeStructField *field)
2275{2290{
...@@ -3066,6 +3081,13 @@ static IrInstruction *ir_instruction_enumtagname_get_dep(IrInstructionEnumTagNam...@@ -3066,6 +3081,13 @@ static IrInstruction *ir_instruction_enumtagname_get_dep(IrInstructionEnumTagNam
3066 }3081 }
3067}3082}
30683083
3084static IrInstruction *ir_instruction_enumtagtype_get_dep(IrInstructionEnumTagType *instruction, size_t index) {
3085 switch (index) {
3086 case 0: return instruction->target;
3087 default: return nullptr;
3088 }
3089}
3090
3069static IrInstruction *ir_instruction_fieldparentptr_get_dep(IrInstructionFieldParentPtr *instruction, size_t index) {3091static IrInstruction *ir_instruction_fieldparentptr_get_dep(IrInstructionFieldParentPtr *instruction, size_t index) {
3070 switch (index) {3092 switch (index) {
3071 case 0: return instruction->type_value;3093 case 0: return instruction->type_value;
...@@ -3326,6 +3348,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t...@@ -3326,6 +3348,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
3326 return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index);3348 return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index);
3327 case IrInstructionIdEnumTagName:3349 case IrInstructionIdEnumTagName:
3328 return ir_instruction_enumtagname_get_dep((IrInstructionEnumTagName *) instruction, index);3350 return ir_instruction_enumtagname_get_dep((IrInstructionEnumTagName *) instruction, index);
3351 case IrInstructionIdEnumTagType:
3352 return ir_instruction_enumtagtype_get_dep((IrInstructionEnumTagType *) instruction, index);
3329 case IrInstructionIdFieldParentPtr:3353 case IrInstructionIdFieldParentPtr:
3330 return ir_instruction_fieldparentptr_get_dep((IrInstructionFieldParentPtr *) instruction, index);3354 return ir_instruction_fieldparentptr_get_dep((IrInstructionFieldParentPtr *) instruction, index);
3331 case IrInstructionIdOffsetOf:3355 case IrInstructionIdOffsetOf:
...@@ -4681,6 +4705,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4681,6 +4705,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4681 IrInstruction *actual_tag = ir_build_enum_tag(irb, scope, node, arg0_value);4705 IrInstruction *actual_tag = ir_build_enum_tag(irb, scope, node, arg0_value);
4682 return ir_build_enum_tag_name(irb, scope, node, actual_tag);4706 return ir_build_enum_tag_name(irb, scope, node, actual_tag);
4683 }4707 }
4708 case BuiltinFnIdEnumTagType:
4709 {
4710 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4711 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4712 if (arg0_value == irb->codegen->invalid_instruction)
4713 return arg0_value;
4714
4715 return ir_build_enum_tag_type(irb, scope, node, arg0_value);
4716 }
4684 case BuiltinFnIdFieldParentPtr:4717 case BuiltinFnIdFieldParentPtr:
4685 {4718 {
4686 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);4719 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -15831,6 +15864,27 @@ static TypeTableEntry *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruc...@@ -15831,6 +15864,27 @@ static TypeTableEntry *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruc
15831 return ira->codegen->builtin_types.entry_type;15864 return ira->codegen->builtin_types.entry_type;
15832}15865}
1583315866
15867static TypeTableEntry *ir_analyze_instruction_enum_tag_type(IrAnalyze *ira, IrInstructionEnumTagType *instruction) {
15868 IrInstruction *target_inst = instruction->target->other;
15869 TypeTableEntry *enum_type = ir_resolve_type(ira, target_inst);
15870 if (type_is_invalid(enum_type))
15871 return ira->codegen->builtin_types.entry_invalid;
15872 if (enum_type->id != TypeTableEntryIdEnum) {
15873 ir_add_error(ira, target_inst, buf_sprintf("expected enum, found '%s'", buf_ptr(&enum_type->name)));
15874 return ira->codegen->builtin_types.entry_invalid;
15875 }
15876 ensure_complete_type(ira->codegen, enum_type);
15877 if (type_is_invalid(enum_type))
15878 return ira->codegen->builtin_types.entry_invalid;
15879
15880 TypeTableEntry *non_int_tag_type = enum_type->data.enumeration.tag_type;
15881 assert(non_int_tag_type->id == TypeTableEntryIdEnumTag);
15882
15883 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
15884 out_val->data.x_type = non_int_tag_type->data.enum_tag.int_type;
15885 return ira->codegen->builtin_types.entry_type;
15886}
15887
15834static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {15888static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
15835 switch (instruction->id) {15889 switch (instruction->id) {
15836 case IrInstructionIdInvalid:15890 case IrInstructionIdInvalid:
...@@ -16029,6 +16083,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -16029,6 +16083,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
16029 return ir_analyze_instruction_set_align_stack(ira, (IrInstructionSetAlignStack *)instruction);16083 return ir_analyze_instruction_set_align_stack(ira, (IrInstructionSetAlignStack *)instruction);
16030 case IrInstructionIdArgType:16084 case IrInstructionIdArgType:
16031 return ir_analyze_instruction_arg_type(ira, (IrInstructionArgType *)instruction);16085 return ir_analyze_instruction_arg_type(ira, (IrInstructionArgType *)instruction);
16086 case IrInstructionIdEnumTagType:
16087 return ir_analyze_instruction_enum_tag_type(ira, (IrInstructionEnumTagType *)instruction);
16032 }16088 }
16033 zig_unreachable();16089 zig_unreachable();
16034}16090}
...@@ -16214,6 +16270,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -16214,6 +16270,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
16214 case IrInstructionIdAlignCast:16270 case IrInstructionIdAlignCast:
16215 case IrInstructionIdOpaqueType:16271 case IrInstructionIdOpaqueType:
16216 case IrInstructionIdArgType:16272 case IrInstructionIdArgType:
16273 case IrInstructionIdEnumTagType:
16217 return false;16274 return false;
16218 case IrInstructionIdAsm:16275 case IrInstructionIdAsm:
16219 {16276 {
src/ir_print.cpp+9
...@@ -994,6 +994,12 @@ static void ir_print_arg_type(IrPrint *irp, IrInstructionArgType *instruction) {...@@ -994,6 +994,12 @@ static void ir_print_arg_type(IrPrint *irp, IrInstructionArgType *instruction) {
994 fprintf(irp->f, ")");994 fprintf(irp->f, ")");
995}995}
996996
997static void ir_print_enum_tag_type(IrPrint *irp, IrInstructionEnumTagType *instruction) {
998 fprintf(irp->f, "@EnumTagType(");
999 ir_print_other_instruction(irp, instruction->target);
1000 fprintf(irp->f, ")");
1001}
1002
9971003
998static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {1004static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
999 ir_print_prefix(irp, instruction);1005 ir_print_prefix(irp, instruction);
...@@ -1312,6 +1318,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1312,6 +1318,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1312 case IrInstructionIdArgType:1318 case IrInstructionIdArgType:
1313 ir_print_arg_type(irp, (IrInstructionArgType *)instruction);1319 ir_print_arg_type(irp, (IrInstructionArgType *)instruction);
1314 break;1320 break;
1321 case IrInstructionIdEnumTagType:
1322 ir_print_enum_tag_type(irp, (IrInstructionEnumTagType *)instruction);
1323 break;
1315 }1324 }
1316 fprintf(irp->f, "\n");1325 fprintf(irp->f, "\n");
1317}1326}
src/parser.cpp+6-1
...@@ -2377,7 +2377,7 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi...@@ -2377,7 +2377,7 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi
2377}2377}
23782378
2379/*2379/*
2380ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" 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(":" Expression) ","
2383*/2383*/
...@@ -2415,6 +2415,10 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2415,6 +2415,10 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
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
2418 if (kind == ContainerKindEnum || kind == ContainerKindStruct) {
2419 node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, false);
2420 }
2421
2418 ast_eat_token(pc, token_index, TokenIdLBrace);2422 ast_eat_token(pc, token_index, TokenIdLBrace);
24192423
2420 for (;;) {2424 for (;;) {
...@@ -2804,6 +2808,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2804,6 +2808,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2804 case NodeTypeContainerDecl:2808 case NodeTypeContainerDecl:
2805 visit_node_list(&node->data.container_decl.fields, visit, context);2809 visit_node_list(&node->data.container_decl.fields, visit, context);
2806 visit_node_list(&node->data.container_decl.decls, visit, context);2810 visit_node_list(&node->data.container_decl.decls, visit, context);
2811 visit_field(&node->data.container_decl.init_arg_expr, visit, context);
2807 break;2812 break;
2808 case NodeTypeStructField:2813 case NodeTypeStructField:
2809 visit_field(&node->data.struct_field.type, visit, context);2814 visit_field(&node->data.struct_field.type, visit, context);
src/translate_c.cpp+11-1
...@@ -651,6 +651,14 @@ static bool c_is_unsigned_integer(Context *c, QualType qt) {...@@ -651,6 +651,14 @@ static bool c_is_unsigned_integer(Context *c, QualType qt) {
651 }651 }
652}652}
653653
654static bool c_is_builtin_type(Context *c, QualType qt, BuiltinType::Kind kind) {
655 const Type *c_type = qual_type_canon(qt);
656 if (c_type->getTypeClass() != Type::Builtin)
657 return false;
658 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
659 return builtin_ty->getKind() == kind;
660}
661
654static bool c_is_float(Context *c, QualType qt) {662static bool c_is_float(Context *c, QualType qt) {
655 const Type *c_type = qt.getTypePtr();663 const Type *c_type = qt.getTypePtr();
656 if (c_type->getTypeClass() != Type::Builtin)664 if (c_type->getTypeClass() != Type::Builtin)
...@@ -3426,7 +3434,9 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3426,7 +3434,9 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3426 AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);3434 AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);
3427 enum_node->data.container_decl.kind = ContainerKindEnum;3435 enum_node->data.container_decl.kind = ContainerKindEnum;
3428 enum_node->data.container_decl.layout = ContainerLayoutExtern;3436 enum_node->data.container_decl.layout = ContainerLayoutExtern;
3429 enum_node->data.container_decl.init_arg_expr = tag_int_type;3437 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt)) {
3438 enum_node->data.container_decl.init_arg_expr = tag_int_type;
3439 }
34303440
3431 enum_node->data.container_decl.fields.resize(field_count);3441 enum_node->data.container_decl.fields.resize(field_count);
3432 uint32_t i = 0;3442 uint32_t i = 0;
test/cases/enum.zig+24
...@@ -190,3 +190,27 @@ test "enum sizes" {...@@ -190,3 +190,27 @@ test "enum sizes" {
190 assert(@sizeOf(ValueCount257) == 2);190 assert(@sizeOf(ValueCount257) == 2);
191 }191 }
192}192}
193
194const Small2 = enum (u2) {
195 One,
196 Two,
197};
198const Small = enum (u2) {
199 One,
200 Two,
201 Three,
202 Four,
203};
204
205test "set enum tag type" {
206 {
207 var x = Small.One;
208 x = Small.Two;
209 comptime assert(@EnumTagType(Small) == u2);
210 }
211 {
212 var x = Small2.One;
213 x = Small2.Two;
214 comptime assert(@EnumTagType(Small2) == u2);
215 }
216}
test/compile_errors.zig+28
...@@ -2362,4 +2362,32 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2362,4 +2362,32 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
2362 ".tmp_source.zig:4:25: error: aoeu",2362 ".tmp_source.zig:4:25: error: aoeu",
2363 ".tmp_source.zig:1:36: note: called from here",2363 ".tmp_source.zig:1:36: note: called from here",
2364 ".tmp_source.zig:12:20: note: referenced here");2364 ".tmp_source.zig:12:20: note: referenced here");
2365
2366 cases.add("specify enum tag type that is too small",
2367 \\const Small = enum (u2) {
2368 \\ One,
2369 \\ Two,
2370 \\ Three,
2371 \\ Four,
2372 \\ Five,
2373 \\};
2374 \\
2375 \\export fn entry() {
2376 \\ var x = Small.One;
2377 \\}
2378 ,
2379 ".tmp_source.zig:1:20: error: 'u2' too small to hold all bits; must be at least 'u3'");
2380
2381 cases.add("specify non-integer enum tag type",
2382 \\const Small = enum (f32) {
2383 \\ One,
2384 \\ Two,
2385 \\ Three,
2386 \\};
2387 \\
2388 \\export fn entry() {
2389 \\ var x = Small.One;
2390 \\}
2391 ,
2392 ".tmp_source.zig:1:20: error: expected integer, found 'f32'");
2365}2393}