| author | |
| committer | |
| log | 2ee67b7642cfeef36d8ebbc08080202b5b1d1958 |
| tree | d031afb8e49237cf040b8fe4c2af72ab86239abd |
| parent | 9eb51e20ed1a040a617541303db760f80ffd3aa1 |
also add detection of incorrect pointer alignment at compile-time
of pointers that were constructed with `@intToPtr`.3 files changed, 70 insertions(+), 3 deletions(-)
doc/langref.html.in+51-3| ... | @@ -6649,12 +6649,60 @@ pub fn main() void { | ... | @@ -6649,12 +6649,60 @@ pub fn main() void { |
| 6649 | {#header_close#} | 6649 | {#header_close#} |
| 6650 | 6650 | ||
| 6651 | {#header_open|Invalid Error Set Cast#} | 6651 | {#header_open|Invalid Error Set Cast#} |
| 6652 | <p>TODO</p> | 6652 | <p>At compile-time:</p> |
| 6653 | {#code_begin|test_err|error.B not a member of error set 'Set2'#} | ||
| 6654 | const Set1 = error{ | ||
| 6655 | A, | ||
| 6656 | B, | ||
| 6657 | }; | ||
| 6658 | const Set2 = error{ | ||
| 6659 | A, | ||
| 6660 | C, | ||
| 6661 | }; | ||
| 6662 | comptime { | ||
| 6663 | _ = @errSetCast(Set2, Set1.B); | ||
| 6664 | } | ||
| 6665 | {#code_end#} | ||
| 6666 | <p>At runtime:</p> | ||
| 6667 | {#code_begin|exe_err#} | ||
| 6668 | const Set1 = error{ | ||
| 6669 | A, | ||
| 6670 | B, | ||
| 6671 | }; | ||
| 6672 | const Set2 = error{ | ||
| 6673 | A, | ||
| 6674 | C, | ||
| 6675 | }; | ||
| 6676 | pub fn main() void { | ||
| 6677 | _ = foo(Set1.B); | ||
| 6678 | } | ||
| 6679 | fn foo(set1: Set1) Set2 { | ||
| 6680 | return @errSetCast(Set2, set1); | ||
| 6681 | } | ||
| 6682 | {#code_end#} | ||
| 6653 | {#header_close#} | 6683 | {#header_close#} |
| 6654 | 6684 | ||
| 6655 | {#header_open|Incorrect Pointer Alignment#} | 6685 | {#header_open|Incorrect Pointer Alignment#} |
| 6656 | <p>TODO</p> | 6686 | <p>At compile-time:</p> |
| 6657 | 6687 | {#code_begin|test_err|pointer address 0x1 is not aligned to 4 bytes#} | |
| 6688 | comptime { | ||
| 6689 | const ptr = @intToPtr(*i32, 0x1); | ||
| 6690 | const aligned = @alignCast(4, ptr); | ||
| 6691 | } | ||
| 6692 | {#code_end#} | ||
| 6693 | <p>At runtime:</p> | ||
| 6694 | {#code_begin|exe_err#} | ||
| 6695 | pub fn main() !void { | ||
| 6696 | var array align(4) = []u32{ 0x11111111, 0x11111111 }; | ||
| 6697 | const bytes = @sliceToBytes(array[0..]); | ||
| 6698 | if (foo(bytes) != 0x11111111) return error.Wrong; | ||
| 6699 | } | ||
| 6700 | fn foo(bytes: []u8) u32 { | ||
| 6701 | const slice4 = bytes[1..5]; | ||
| 6702 | const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); | ||
| 6703 | return int_slice[0]; | ||
| 6704 | } | ||
| 6705 | {#code_end#} | ||
| 6658 | {#header_close#} | 6706 | {#header_close#} |
| 6659 | {#header_open|Wrong Union Field Access#} | 6707 | {#header_open|Wrong Union Field Access#} |
| 6660 | <p>TODO</p> | 6708 | <p>TODO</p> |
src/ir.cpp+9| ... | @@ -19370,6 +19370,15 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 | ... | @@ -19370,6 +19370,15 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 |
| 19370 | if (!val) | 19370 | if (!val) |
| 19371 | return ira->codegen->invalid_instruction; | 19371 | return ira->codegen->invalid_instruction; |
| 19372 | 19372 | ||
| 19373 | if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && | ||
| 19374 | val->data.x_ptr.data.hard_coded_addr.addr % align_bytes != 0) | ||
| 19375 | { | ||
| 19376 | ir_add_error(ira, target, | ||
| 19377 | buf_sprintf("pointer address 0x%lx is not aligned to %" PRIu32 " bytes", | ||
| 19378 | val->data.x_ptr.data.hard_coded_addr.addr, align_bytes)); | ||
| 19379 | return ira->codegen->invalid_instruction; | ||
| 19380 | } | ||
| 19381 | |||
| 19373 | IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type); | 19382 | IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type); |
| 19374 | copy_const_val(&result->value, val, false); | 19383 | copy_const_val(&result->value, val, false); |
| 19375 | result->value.type = result_type; | 19384 | result->value.type = result_type; |
test/compile_errors.zig+10| ... | @@ -1,6 +1,16 @@ | ... | @@ -1,6 +1,16 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4 | cases.add( | ||
| 5 | "bad @alignCast at comptime", | ||
| 6 | \\comptime { | ||
| 7 | \\ const ptr = @intToPtr(*i32, 0x1); | ||
| 8 | \\ const aligned = @alignCast(4, ptr); | ||
| 9 | \\} | ||
| 10 | , | ||
| 11 | ".tmp_source.zig:3:35: error: pointer address 0x1 is not aligned to 4 bytes", | ||
| 12 | ); | ||
| 13 | |||
| 4 | cases.add( | 14 | cases.add( |
| 5 | "@ptrToInt on *void", | 15 | "@ptrToInt on *void", |
| 6 | \\export fn entry() bool { | 16 | \\export fn entry() bool { |