authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-06 14:58:24-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-06 14:58:24-05:00
log04612d25d7d33e8c3f08301d668ab94fe7479c84
tree082688c8fa8d27618bea69995a57a50f8700314f
parentb66fb7ceae9029935e5cf3c3752d240a74b6cd7c
parent249cb2aa30bbdd0c30f24ef18097e3b1cd3e0da5

Merge branch 'master' into self-hosted


3 files changed, 166 insertions(+), 35 deletions(-)

src/ir.cpp+129-35
......@@ -7468,6 +7468,17 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
74687468 }
74697469 }
74707470
7471 // implicit union to its enum tag type
7472 if (expected_type->id == TypeTableEntryIdEnum && actual_type->id == TypeTableEntryIdUnion &&
7473 (actual_type->data.unionation.decl_node->data.container_decl.auto_enum ||
7474 actual_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
7475 {
7476 type_ensure_zero_bits_known(ira->codegen, actual_type);
7477 if (actual_type->data.unionation.tag_type == expected_type) {
7478 return ImplicitCastMatchResultYes;
7479 }
7480 }
7481
74717482 // implicit enum to union which has the enum as the tag type
74727483 if (expected_type->id == TypeTableEntryIdUnion && actual_type->id == TypeTableEntryIdEnum &&
74737484 (expected_type->data.unionation.decl_node->data.container_decl.auto_enum ||
......@@ -7508,33 +7519,53 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
75087519 IrInstruction *cur_inst = instructions[i];
75097520 TypeTableEntry *cur_type = cur_inst->value.type;
75107521 TypeTableEntry *prev_type = prev_inst->value.type;
7522
75117523 if (type_is_invalid(cur_type)) {
75127524 return cur_type;
7513 } else if (prev_type->id == TypeTableEntryIdUnreachable) {
7525 }
7526
7527 if (prev_type->id == TypeTableEntryIdUnreachable) {
75147528 prev_inst = cur_inst;
7515 } else if (cur_type->id == TypeTableEntryIdUnreachable) {
75167529 continue;
7517 } else if (prev_type->id == TypeTableEntryIdPureError) {
7530 }
7531
7532 if (cur_type->id == TypeTableEntryIdUnreachable) {
7533 continue;
7534 }
7535
7536 if (prev_type->id == TypeTableEntryIdPureError) {
75187537 prev_inst = cur_inst;
75197538 continue;
7520 } else if (prev_type->id == TypeTableEntryIdNullLit) {
7539 }
7540
7541 if (prev_type->id == TypeTableEntryIdNullLit) {
75217542 prev_inst = cur_inst;
75227543 continue;
7523 } else if (cur_type->id == TypeTableEntryIdPureError) {
7544 }
7545
7546 if (cur_type->id == TypeTableEntryIdPureError) {
75247547 if (prev_type->id == TypeTableEntryIdArray) {
75257548 convert_to_const_slice = true;
75267549 }
75277550 any_are_pure_error = true;
75287551 continue;
7529 } else if (cur_type->id == TypeTableEntryIdNullLit) {
7552 }
7553
7554 if (cur_type->id == TypeTableEntryIdNullLit) {
75307555 any_are_null = true;
75317556 continue;
7532 } else if (types_match_const_cast_only(prev_type, cur_type)) {
7557 }
7558
7559 if (types_match_const_cast_only(prev_type, cur_type)) {
75337560 continue;
7534 } else if (types_match_const_cast_only(cur_type, prev_type)) {
7561 }
7562
7563 if (types_match_const_cast_only(cur_type, prev_type)) {
75357564 prev_inst = cur_inst;
75367565 continue;
7537 } else if (prev_type->id == TypeTableEntryIdInt &&
7566 }
7567
7568 if (prev_type->id == TypeTableEntryIdInt &&
75387569 cur_type->id == TypeTableEntryIdInt &&
75397570 prev_type->data.integral.is_signed == cur_type->data.integral.is_signed)
75407571 {
......@@ -7542,36 +7573,51 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
75427573 prev_inst = cur_inst;
75437574 }
75447575 continue;
7545 } else if (prev_type->id == TypeTableEntryIdFloat &&
7546 cur_type->id == TypeTableEntryIdFloat)
7547 {
7576 }
7577
7578 if (prev_type->id == TypeTableEntryIdFloat && cur_type->id == TypeTableEntryIdFloat) {
75487579 if (cur_type->data.floating.bit_count > prev_type->data.floating.bit_count) {
75497580 prev_inst = cur_inst;
75507581 }
7551 } else if (prev_type->id == TypeTableEntryIdErrorUnion &&
7582 continue;
7583 }
7584
7585 if (prev_type->id == TypeTableEntryIdErrorUnion &&
75527586 types_match_const_cast_only(prev_type->data.error.child_type, cur_type))
75537587 {
75547588 continue;
7555 } else if (cur_type->id == TypeTableEntryIdErrorUnion &&
7589 }
7590
7591 if (cur_type->id == TypeTableEntryIdErrorUnion &&
75567592 types_match_const_cast_only(cur_type->data.error.child_type, prev_type))
75577593 {
75587594 prev_inst = cur_inst;
75597595 continue;
7560 } else if (prev_type->id == TypeTableEntryIdMaybe &&
7596 }
7597
7598 if (prev_type->id == TypeTableEntryIdMaybe &&
75617599 types_match_const_cast_only(prev_type->data.maybe.child_type, cur_type))
75627600 {
75637601 continue;
7564 } else if (cur_type->id == TypeTableEntryIdMaybe &&
7602 }
7603
7604 if (cur_type->id == TypeTableEntryIdMaybe &&
75657605 types_match_const_cast_only(cur_type->data.maybe.child_type, prev_type))
75667606 {
75677607 prev_inst = cur_inst;
75687608 continue;
7569 } else if (cur_type->id == TypeTableEntryIdUndefLit) {
7609 }
7610
7611 if (cur_type->id == TypeTableEntryIdUndefLit) {
75707612 continue;
7571 } else if (prev_type->id == TypeTableEntryIdUndefLit) {
7613 }
7614
7615 if (prev_type->id == TypeTableEntryIdUndefLit) {
75727616 prev_inst = cur_inst;
75737617 continue;
7574 } else if (prev_type->id == TypeTableEntryIdNumLitInt ||
7618 }
7619
7620 if (prev_type->id == TypeTableEntryIdNumLitInt ||
75757621 prev_type->id == TypeTableEntryIdNumLitFloat)
75767622 {
75777623 if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type, false)) {
......@@ -7580,7 +7626,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
75807626 } else {
75817627 return ira->codegen->builtin_types.entry_invalid;
75827628 }
7583 } else if (cur_type->id == TypeTableEntryIdNumLitInt ||
7629 }
7630
7631 if (cur_type->id == TypeTableEntryIdNumLitInt ||
75847632 cur_type->id == TypeTableEntryIdNumLitFloat)
75857633 {
75867634 if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type, false)) {
......@@ -7588,20 +7636,26 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
75887636 } else {
75897637 return ira->codegen->builtin_types.entry_invalid;
75907638 }
7591 } else if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
7639 }
7640
7641 if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
75927642 cur_type->data.array.len != prev_type->data.array.len &&
75937643 types_match_const_cast_only(cur_type->data.array.child_type, prev_type->data.array.child_type))
75947644 {
75957645 convert_to_const_slice = true;
75967646 prev_inst = cur_inst;
75977647 continue;
7598 } else if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
7648 }
7649
7650 if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
75997651 cur_type->data.array.len != prev_type->data.array.len &&
76007652 types_match_const_cast_only(prev_type->data.array.child_type, cur_type->data.array.child_type))
76017653 {
76027654 convert_to_const_slice = true;
76037655 continue;
7604 } else if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) &&
7656 }
7657
7658 if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) &&
76057659 (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
76067660 cur_type->data.array.len == 0) &&
76077661 types_match_const_cast_only(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
......@@ -7609,7 +7663,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
76097663 {
76107664 convert_to_const_slice = false;
76117665 continue;
7612 } else if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) &&
7666 }
7667
7668 if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) &&
76137669 (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
76147670 prev_type->data.array.len == 0) &&
76157671 types_match_const_cast_only(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
......@@ -7618,17 +7674,40 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
76187674 prev_inst = cur_inst;
76197675 convert_to_const_slice = false;
76207676 continue;
7621 } else {
7622 ErrorMsg *msg = ir_add_error_node(ira, source_node,
7623 buf_sprintf("incompatible types: '%s' and '%s'",
7624 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
7625 add_error_note(ira->codegen, msg, prev_inst->source_node,
7626 buf_sprintf("type '%s' here", buf_ptr(&prev_type->name)));
7627 add_error_note(ira->codegen, msg, cur_inst->source_node,
7628 buf_sprintf("type '%s' here", buf_ptr(&cur_type->name)));
7677 }
76297678
7630 return ira->codegen->builtin_types.entry_invalid;
7679 if (prev_type->id == TypeTableEntryIdEnum && cur_type->id == TypeTableEntryIdUnion &&
7680 (cur_type->data.unionation.decl_node->data.container_decl.auto_enum || cur_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
7681 {
7682 type_ensure_zero_bits_known(ira->codegen, cur_type);
7683 if (type_is_invalid(cur_type))
7684 return ira->codegen->builtin_types.entry_invalid;
7685 if (cur_type->data.unionation.tag_type == prev_type) {
7686 continue;
7687 }
7688 }
7689
7690 if (cur_type->id == TypeTableEntryIdEnum && prev_type->id == TypeTableEntryIdUnion &&
7691 (prev_type->data.unionation.decl_node->data.container_decl.auto_enum || prev_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
7692 {
7693 type_ensure_zero_bits_known(ira->codegen, prev_type);
7694 if (type_is_invalid(prev_type))
7695 return ira->codegen->builtin_types.entry_invalid;
7696 if (prev_type->data.unionation.tag_type == cur_type) {
7697 prev_inst = cur_inst;
7698 continue;
7699 }
76317700 }
7701
7702 ErrorMsg *msg = ir_add_error_node(ira, source_node,
7703 buf_sprintf("incompatible types: '%s' and '%s'",
7704 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
7705 add_error_note(ira->codegen, msg, prev_inst->source_node,
7706 buf_sprintf("type '%s' here", buf_ptr(&prev_type->name)));
7707 add_error_note(ira->codegen, msg, cur_inst->source_node,
7708 buf_sprintf("type '%s' here", buf_ptr(&cur_type->name)));
7709
7710 return ira->codegen->builtin_types.entry_invalid;
76327711 }
76337712 if (convert_to_const_slice) {
76347713 assert(prev_inst->value.type->id == TypeTableEntryIdArray);
......@@ -9425,6 +9504,10 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
94259504 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2);
94269505 if (type_is_invalid(resolved_type))
94279506 return resolved_type;
9507 type_ensure_zero_bits_known(ira->codegen, resolved_type);
9508 if (type_is_invalid(resolved_type))
9509 return resolved_type;
9510
94289511
94299512 AstNode *source_node = bin_op_instruction->base.source_node;
94309513 switch (resolved_type->id) {
......@@ -9489,7 +9572,8 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
94899572
94909573 ConstExprValue *op1_val = &casted_op1->value;
94919574 ConstExprValue *op2_val = &casted_op2->value;
9492 if ((value_is_comptime(op1_val) && value_is_comptime(op2_val)) || resolved_type->id == TypeTableEntryIdVoid) {
9575 bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type);
9576 if (one_possible_value || (value_is_comptime(op1_val) && value_is_comptime(op2_val))) {
94939577 bool answer;
94949578 if (resolved_type->id == TypeTableEntryIdNumLitFloat || resolved_type->id == TypeTableEntryIdFloat) {
94959579 Cmp cmp_result = float_cmp(op1_val, op2_val);
......@@ -9498,7 +9582,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
94989582 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
94999583 answer = resolve_cmp_op_id(op_id, cmp_result);
95009584 } else {
9501 bool are_equal = resolved_type->id == TypeTableEntryIdVoid || const_values_equal(op1_val, op2_val);
9585 bool are_equal = one_possible_value || const_values_equal(op1_val, op2_val);
95029586 if (op_id == IrBinOpCmpEq) {
95039587 answer = are_equal;
95049588 } else if (op_id == IrBinOpCmpNotEq) {
......@@ -13090,6 +13174,16 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1309013174 return tag_type;
1309113175 }
1309213176 case TypeTableEntryIdEnum: {
13177 type_ensure_zero_bits_known(ira->codegen, target_type);
13178 if (type_is_invalid(target_type))
13179 return ira->codegen->builtin_types.entry_invalid;
13180 if (target_type->data.enumeration.src_field_count < 2) {
13181 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
13182 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
13183 bigint_init_bigint(&out_val->data.x_enum_tag, &only_field->value);
13184 return target_type;
13185 }
13186
1309313187 if (pointee_val) {
1309413188 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
1309513189 bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_enum_tag);
test/cases/enum.zig+28
......@@ -349,3 +349,31 @@ test "cast integer literal to enum" {
349349 assert(MultipleChoice2(0) == MultipleChoice2.Unspecified1);
350350 assert(MultipleChoice2(40) == MultipleChoice2.B);
351351}
352
353const EnumWithOneMember = enum {
354 Eof,
355};
356
357fn doALoopThing(id: EnumWithOneMember) {
358 while (true) {
359 if (id == EnumWithOneMember.Eof) {
360 break;
361 }
362 @compileError("above if condition should be comptime");
363 }
364}
365
366test "comparison operator on enum with one member is comptime known" {
367 doALoopThing(EnumWithOneMember.Eof);
368}
369
370const State = enum {
371 Start,
372};
373test "switch on enum with one member is comptime known" {
374 var state = State.Start;
375 switch (state) {
376 State.Start => return,
377 }
378 @compileError("analysis should not reach here");
379}
test/cases/union.zig+9
......@@ -197,3 +197,12 @@ test "cast tag type of union to union" {
197197}
198198const Letter2 = enum { A, B, C };
199199const Value2 = union(Letter2) { A: i32, B, C, };
200
201test "implicit cast union to its tag type" {
202 var x: Value2 = Letter2.B;
203 assert(x == Letter2.B);
204 giveMeLetterB(x);
205}
206fn giveMeLetterB(x: Letter2) {
207 assert(x == Value2.B);
208}