| author | |
| committer | |
| log | b62e2fd8703129fcf0dc80675800f005e84ee724 |
| tree | c70341d5db1c79901ce58d86c1aa24f5c972d57d |
| parent | 5786df933d37d52d57fef9c28acb9c2c23128d31 |
see #30511 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 ")" |
| 5837 | 5843 | ||
| 5838 | KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable" | 5844 | KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable" |
| 5839 | 5845 | ||
| 5840 | ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"</code></pre> | 5846 | ContainerDecl = 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 | }; |
| 2697 | 2699 | ||
| 2700 | struct IrInstructionEnumTagType { | ||
| 2701 | IrInstruction base; | ||
| 2702 | |||
| 2703 | IrInstruction *target; | ||
| 2704 | }; | ||
| 2705 | |||
| 2698 | struct IrInstructionFieldParentPtr { | 2706 | struct IrInstructionFieldParentPtr { |
| 2699 | IrInstruction base; | 2707 | IrInstruction base; |
| 2700 | 2708 |
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); |
| 1268 | 1268 | ||
| 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)); |
| 1271 | 1271 | ||
| 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 | } |
| 1392 | 1392 | ||
| 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; |
| 1396 | 1415 |
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 | } |
| 553 | 553 | ||
| 554 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTagType *) { | ||
| 555 | return IrInstructionIdEnumTagType; | ||
| 556 | } | ||
| 557 | |||
| 554 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldParentPtr *) { | 558 | static 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 | } |
| 2272 | 2276 | ||
| 2277 | static 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 | |||
| 2273 | static IrInstruction *ir_build_field_parent_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2288 | static 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 | } |
| 3068 | 3083 | ||
| 3084 | static 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 | |||
| 3069 | static IrInstruction *ir_instruction_fieldparentptr_get_dep(IrInstructionFieldParentPtr *instruction, size_t index) { | 3091 | static 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 | } |
| 15833 | 15866 | ||
| 15867 | static 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 | |||
| 15834 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 15888 | static 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 | } |
| 996 | 996 | ||
| 997 | static 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 | |||
| 997 | 1003 | ||
| 998 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 1004 | static 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 | } |
| 2378 | 2378 | ||
| 2379 | /* | 2379 | /* |
| 2380 | ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}" | 2380 | ContainerDecl = option("extern" | "packed") ("struct" | "union" | ("enum" option(GroupedExpression))) "{" many(ContainerMember) "}" |
| 2381 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) | 2381 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) |
| 2382 | ContainerField = Symbol option(":" Expression) "," | 2382 | ContainerField = 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; |
| 2417 | 2417 | ||
| 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); |
| 2419 | 2423 | ||
| 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 | } |
| 653 | 653 | ||
| 654 | static 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 | |||
| 654 | static bool c_is_float(Context *c, QualType qt) { | 662 | static 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 | } | ||
| 3430 | 3440 | ||
| 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 | |||
| 194 | const Small2 = enum (u2) { | ||
| 195 | One, | ||
| 196 | Two, | ||
| 197 | }; | ||
| 198 | const Small = enum (u2) { | ||
| 199 | One, | ||
| 200 | Two, | ||
| 201 | Three, | ||
| 202 | Four, | ||
| 203 | }; | ||
| 204 | |||
| 205 | test "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 | } |