| author | |
| committer | |
| log | 32b37e695aa0581b863a395e0a28b7b4aa76c07d |
| tree | 6c942241282c9c1163bb22b75f91efda49712291 |
| parent | 37318bf15138d0a7b158b32ca43cbcdcf5382942 |
| signature |
closes #36675 files changed, 49 insertions(+), 11 deletions(-)
src/analyze.cpp+22-1| ... | @@ -5432,7 +5432,7 @@ bool fn_eval_eql(Scope *a, Scope *b) { | ... | @@ -5432,7 +5432,7 @@ bool fn_eval_eql(Scope *a, Scope *b) { |
| 5432 | return false; | 5432 | return false; |
| 5433 | } | 5433 | } |
| 5434 | 5434 | ||
| 5435 | // Whether the type has bits at runtime. | 5435 | // Deprecated. Use type_has_bits2. |
| 5436 | bool type_has_bits(ZigType *type_entry) { | 5436 | bool type_has_bits(ZigType *type_entry) { |
| 5437 | assert(type_entry != nullptr); | 5437 | assert(type_entry != nullptr); |
| 5438 | assert(!type_is_invalid(type_entry)); | 5438 | assert(!type_is_invalid(type_entry)); |
| ... | @@ -5440,6 +5440,27 @@ bool type_has_bits(ZigType *type_entry) { | ... | @@ -5440,6 +5440,27 @@ bool type_has_bits(ZigType *type_entry) { |
| 5440 | return type_entry->abi_size != 0; | 5440 | return type_entry->abi_size != 0; |
| 5441 | } | 5441 | } |
| 5442 | 5442 | ||
| 5443 | // Whether the type has bits at runtime. | ||
| 5444 | Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result) { | ||
| 5445 | Error err; | ||
| 5446 | |||
| 5447 | if (type_is_invalid(type_entry)) | ||
| 5448 | return ErrorSemanticAnalyzeFail; | ||
| 5449 | |||
| 5450 | if (type_entry->id == ZigTypeIdStruct && | ||
| 5451 | type_entry->data.structure.resolve_status == ResolveStatusBeingInferred) | ||
| 5452 | { | ||
| 5453 | *result = true; | ||
| 5454 | return ErrorNone; | ||
| 5455 | } | ||
| 5456 | |||
| 5457 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) | ||
| 5458 | return err; | ||
| 5459 | |||
| 5460 | *result = type_entry->abi_size != 0; | ||
| 5461 | return ErrorNone; | ||
| 5462 | } | ||
| 5463 | |||
| 5443 | // Whether you can infer the value based solely on the type. | 5464 | // Whether you can infer the value based solely on the type. |
| 5444 | OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { | 5465 | OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { |
| 5445 | assert(type_entry != nullptr); | 5466 | assert(type_entry != nullptr); |
src/analyze.hpp+2| ... | @@ -46,6 +46,8 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type); | ... | @@ -46,6 +46,8 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type); |
| 46 | bool handle_is_ptr(ZigType *type_entry); | 46 | bool handle_is_ptr(ZigType *type_entry); |
| 47 | 47 | ||
| 48 | bool type_has_bits(ZigType *type_entry); | 48 | bool type_has_bits(ZigType *type_entry); |
| 49 | Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result); | ||
| 50 | |||
| 49 | Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result); | 51 | Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result); |
| 50 | bool ptr_allows_addr_zero(ZigType *ptr_type); | 52 | bool ptr_allows_addr_zero(ZigType *ptr_type); |
| 51 | bool type_is_nonnull_ptr(ZigType *type); | 53 | bool type_is_nonnull_ptr(ZigType *type); |
src/codegen.cpp+6-1| ... | @@ -3622,9 +3622,14 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_ | ... | @@ -3622,9 +3622,14 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_ |
| 3622 | } | 3622 | } |
| 3623 | 3623 | ||
| 3624 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { | 3624 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { |
| 3625 | Error err; | ||
| 3626 | |||
| 3625 | ZigType *ptr_type = instruction->ptr->value.type; | 3627 | ZigType *ptr_type = instruction->ptr->value.type; |
| 3626 | assert(ptr_type->id == ZigTypeIdPointer); | 3628 | assert(ptr_type->id == ZigTypeIdPointer); |
| 3627 | if (!type_has_bits(ptr_type)) | 3629 | bool ptr_type_has_bits; |
| 3630 | if ((err = type_has_bits2(g, ptr_type, &ptr_type_has_bits))) | ||
| 3631 | codegen_report_errors_and_exit(g); | ||
| 3632 | if (!ptr_type_has_bits) | ||
| 3628 | return nullptr; | 3633 | return nullptr; |
| 3629 | if (instruction->ptr->ref_count == 0) { | 3634 | if (instruction->ptr->ref_count == 0) { |
| 3630 | // In this case, this StorePtr instruction should be elided. Something happened like this: | 3635 | // In this case, this StorePtr instruction should be elided. Something happened like this: |
src/ir.cpp+9-8| ... | @@ -15513,15 +15513,16 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in | ... | @@ -15513,15 +15513,16 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in |
| 15513 | result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer; | 15513 | result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer; |
| 15514 | result->base.value.data.x_ptr.data.ref.pointee = pointee; | 15514 | result->base.value.data.x_ptr.data.ref.pointee = pointee; |
| 15515 | 15515 | ||
| 15516 | if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown))) | 15516 | bool var_type_has_bits; |
| 15517 | if ((err = type_has_bits2(ira->codegen, var_type, &var_type_has_bits))) | ||
| 15517 | return ira->codegen->invalid_instruction; | 15518 | return ira->codegen->invalid_instruction; |
| 15518 | if (align != 0) { | 15519 | if (align != 0) { |
| 15519 | if ((err = type_resolve(ira->codegen, var_type, ResolveStatusAlignmentKnown))) | 15520 | if ((err = type_resolve(ira->codegen, var_type, ResolveStatusAlignmentKnown))) |
| 15520 | return ira->codegen->invalid_instruction; | 15521 | return ira->codegen->invalid_instruction; |
| 15521 | if (!type_has_bits(var_type)) { | 15522 | if (!var_type_has_bits) { |
| 15522 | ir_add_error(ira, source_inst, | 15523 | ir_add_error(ira, source_inst, |
| 15523 | buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned", | 15524 | buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned", |
| 15524 | name_hint, buf_ptr(&var_type->name))); | 15525 | name_hint, buf_ptr(&var_type->name))); |
| 15525 | return ira->codegen->invalid_instruction; | 15526 | return ira->codegen->invalid_instruction; |
| 15526 | } | 15527 | } |
| 15527 | } | 15528 | } |
| ... | @@ -22138,15 +22139,15 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct | ... | @@ -22138,15 +22139,15 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct |
| 22138 | } | 22139 | } |
| 22139 | for (size_t i = 0; i < errors_len; i += 1) { | 22140 | for (size_t i = 0; i < errors_len; i += 1) { |
| 22140 | Stage2ErrorMsg *clang_err = &errors_ptr[i]; | 22141 | Stage2ErrorMsg *clang_err = &errors_ptr[i]; |
| 22141 | 		// Clang can emit "too many errors, stopping now", in which case `source` and `filename_ptr` are null | 22142 | // Clang can emit "too many errors, stopping now", in which case `source` and `filename_ptr` are null |
| 22142 | 		if (clang_err->source && clang_err->filename_ptr) { | 22143 | if (clang_err->source && clang_err->filename_ptr) { |
| 22143 | ErrorMsg *err_msg = err_msg_create_with_offset( | 22144 | ErrorMsg *err_msg = err_msg_create_with_offset( |
| 22144 | clang_err->filename_ptr ? | 22145 | clang_err->filename_ptr ? |
| 22145 | buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(), | 22146 | buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(), |
| 22146 | clang_err->line, clang_err->column, clang_err->offset, clang_err->source, | 22147 | clang_err->line, clang_err->column, clang_err->offset, clang_err->source, |
| 22147 | buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); | 22148 | buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); |
| 22148 | err_msg_add_note(parent_err_msg, err_msg); | 22149 | err_msg_add_note(parent_err_msg, err_msg); |
| 22149 | 		} | 22150 | } |
| 22150 | } | 22151 | } |
| 22151 | 22152 | ||
| 22152 | return ira->codegen->invalid_instruction; | 22153 | return ira->codegen->invalid_instruction; |
test/stage1/behavior/struct.zig+10-1| ... | @@ -755,7 +755,7 @@ test "fully anonymous struct" { | ... | @@ -755,7 +755,7 @@ test "fully anonymous struct" { |
| 755 | test "fully anonymous list literal" { | 755 | test "fully anonymous list literal" { |
| 756 | const S = struct { | 756 | const S = struct { |
| 757 | fn doTheTest() void { | 757 | fn doTheTest() void { |
| 758 | dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi"}); | 758 | dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" }); |
| 759 | } | 759 | } |
| 760 | fn dump(args: var) void { | 760 | fn dump(args: var) void { |
| 761 | expect(args.@"0" == 1234); | 761 | expect(args.@"0" == 1234); |
| ... | @@ -768,3 +768,12 @@ test "fully anonymous list literal" { | ... | @@ -768,3 +768,12 @@ test "fully anonymous list literal" { |
| 768 | S.doTheTest(); | 768 | S.doTheTest(); |
| 769 | comptime S.doTheTest(); | 769 | comptime S.doTheTest(); |
| 770 | } | 770 | } |
| 771 | |||
| 772 | test "anonymous struct literal assigned to variable" { | ||
| 773 | var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) }; | ||
| 774 | expect(vec.@"0" == 22); | ||
| 775 | expect(vec.@"1" == 55); | ||
| 776 | expect(vec.@"2" == 99); | ||
| 777 | vec.@"1" += 1; | ||
| 778 | expect(vec.@"1" == 56); | ||
| 779 | } |