Skip to content

Commit

Permalink
langref: docs for invalid error set cast and incorrect pointer alignment
Browse files Browse the repository at this point in the history
also add detection of incorrect pointer alignment at compile-time
of pointers that were constructed with `@intToPtr`.
  • Loading branch information
andrewrk committed Jul 9, 2018
1 parent 9eb51e2 commit 2ee67b7
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 3 deletions.
54 changes: 51 additions & 3 deletions doc/langref.html.in
Expand Up @@ -6649,12 +6649,60 @@ pub fn main() void {
{#header_close#}

{#header_open|Invalid Error Set Cast#}
<p>TODO</p>
<p>At compile-time:</p>
{#code_begin|test_err|error.B not a member of error set 'Set2'#}
const Set1 = error{
A,
B,
};
const Set2 = error{
A,
C,
};
comptime {
_ = @errSetCast(Set2, Set1.B);
}
{#code_end#}
<p>At runtime:</p>
{#code_begin|exe_err#}
const Set1 = error{
A,
B,
};
const Set2 = error{
A,
C,
};
pub fn main() void {
_ = foo(Set1.B);
}
fn foo(set1: Set1) Set2 {
return @errSetCast(Set2, set1);
}
{#code_end#}
{#header_close#}

{#header_open|Incorrect Pointer Alignment#}
<p>TODO</p>

<p>At compile-time:</p>
{#code_begin|test_err|pointer address 0x1 is not aligned to 4 bytes#}
comptime {
const ptr = @intToPtr(*i32, 0x1);
const aligned = @alignCast(4, ptr);
}
{#code_end#}
<p>At runtime:</p>
{#code_begin|exe_err#}
pub fn main() !void {
var array align(4) = []u32{ 0x11111111, 0x11111111 };
const bytes = @sliceToBytes(array[0..]);
if (foo(bytes) != 0x11111111) return error.Wrong;
}
fn foo(bytes: []u8) u32 {
const slice4 = bytes[1..5];
const int_slice = @bytesToSlice(u32, @alignCast(4, slice4));
return int_slice[0];
}
{#code_end#}
{#header_close#}
{#header_open|Wrong Union Field Access#}
<p>TODO</p>
Expand Down
9 changes: 9 additions & 0 deletions src/ir.cpp
Expand Up @@ -19370,6 +19370,15 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
if (!val)
return ira->codegen->invalid_instruction;

if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
val->data.x_ptr.data.hard_coded_addr.addr % align_bytes != 0)
{
ir_add_error(ira, target,
buf_sprintf("pointer address 0x%lx is not aligned to %" PRIu32 " bytes",
val->data.x_ptr.data.hard_coded_addr.addr, align_bytes));
return ira->codegen->invalid_instruction;
}

IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type);
copy_const_val(&result->value, val, false);
result->value.type = result_type;
Expand Down
10 changes: 10 additions & 0 deletions test/compile_errors.zig
@@ -1,6 +1,16 @@
const tests = @import("tests.zig");

pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"bad @alignCast at comptime",
\\comptime {
\\ const ptr = @intToPtr(*i32, 0x1);
\\ const aligned = @alignCast(4, ptr);
\\}
,
".tmp_source.zig:3:35: error: pointer address 0x1 is not aligned to 4 bytes",
);

cases.add(
"@ptrToInt on *void",
\\export fn entry() bool {
Expand Down

0 comments on commit 2ee67b7

Please sign in to comment.