authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-29 15:19:15-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-29 15:19:15-04:00
logbe94299666e57486be6bdb8fee2b79dbf3623c5d
treee0a04a80df130e5aee55b6cfa5d309821fbd8e97
parent8f682efbc5abf4d631f60310f95b998c6fe44669

prevent implicitly increasing pointer alignment

See #37

3 files changed, 65 insertions(+), 10 deletions(-)

src/analyze.cpp+15-10
...@@ -2615,25 +2615,30 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *...@@ -2615,25 +2615,30 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *
2615 (!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const) &&2615 (!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const) &&
2616 (!actual_type->data.pointer.is_volatile || expected_type->data.pointer.is_volatile) &&2616 (!actual_type->data.pointer.is_volatile || expected_type->data.pointer.is_volatile) &&
2617 actual_type->data.pointer.bit_offset == expected_type->data.pointer.bit_offset &&2617 actual_type->data.pointer.bit_offset == expected_type->data.pointer.bit_offset &&
2618 actual_type->data.pointer.unaligned_bit_count == expected_type->data.pointer.unaligned_bit_count)2618 actual_type->data.pointer.unaligned_bit_count == expected_type->data.pointer.unaligned_bit_count &&
2619 actual_type->data.pointer.alignment >= expected_type->data.pointer.alignment)
2619 {2620 {
2620 return types_match_const_cast_only(expected_type->data.pointer.child_type,2621 return types_match_const_cast_only(expected_type->data.pointer.child_type,
2621 actual_type->data.pointer.child_type);2622 actual_type->data.pointer.child_type);
2622 }2623 }
26232624
2624 // unknown size array const2625 // slice const
2625 if (expected_type->id == TypeTableEntryIdStruct &&2626 if (expected_type->id == TypeTableEntryIdStruct &&
2626 actual_type->id == TypeTableEntryIdStruct &&2627 actual_type->id == TypeTableEntryIdStruct &&
2627 expected_type->data.structure.is_slice &&2628 expected_type->data.structure.is_slice &&
2628 actual_type->data.structure.is_slice &&2629 actual_type->data.structure.is_slice)
2629 (!actual_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
2630 expected_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const) &&
2631 (!actual_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_volatile ||
2632 expected_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_volatile))
2633 {2630 {
2634 return types_match_const_cast_only(2631 TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
2635 expected_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,2632 TypeTableEntry *expected_ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry;
2636 actual_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type);2633 if ((!actual_ptr_type->data.pointer.is_const || expected_ptr_type->data.pointer.is_const) &&
2634 (!actual_ptr_type->data.pointer.is_volatile || expected_ptr_type->data.pointer.is_volatile) &&
2635 actual_ptr_type->data.pointer.bit_offset == expected_ptr_type->data.pointer.bit_offset &&
2636 actual_ptr_type->data.pointer.unaligned_bit_count == expected_ptr_type->data.pointer.unaligned_bit_count &&
2637 actual_ptr_type->data.pointer.alignment >= expected_ptr_type->data.pointer.alignment)
2638 {
2639 return types_match_const_cast_only(expected_ptr_type->data.pointer.child_type,
2640 actual_ptr_type->data.pointer.child_type);
2641 }
2637 }2642 }
26382643
2639 // maybe2644 // maybe
test/cases/align.zig+15
...@@ -38,3 +38,18 @@ test "bit field alignment" {...@@ -38,3 +38,18 @@ test "bit field alignment" {
38test "default alignment allows unspecified in type syntax" {38test "default alignment allows unspecified in type syntax" {
39 assert(&u32 == &align @alignOf(u32) u32);39 assert(&u32 == &align @alignOf(u32) u32);
40}40}
41
42test "implicitly decreasing pointer alignment" {
43 const a: u32 align 4 = 3;
44 const b: u32 align 8 = 4;
45 assert(addUnaligned(&a, &b) == 7);
46}
47
48fn addUnaligned(a: &align 1 const u32, b: &align 1 const u32) -> u32 { *a + *b }
49
50test "implicitly decreasing slice alignment" {
51 const a: u32 align 4 = 3;
52 const b: u32 align 8 = 4;
53 assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7);
54}
55fn addUnalignedSlice(a: []align 1 const u32, b: []align 1 const u32) -> u32 { a[0] + b[0] }
test/compile_errors.zig+35
...@@ -1976,4 +1976,39 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -1976,4 +1976,39 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
1976 \\}1976 \\}
1977 ,1977 ,
1978 ".tmp_source.zig:1:1: error: declaration shadows type 'u16'");1978 ".tmp_source.zig:1:1: error: declaration shadows type 'u16'");
1979
1980 cases.add("implicitly increasing pointer alignment",
1981 \\const Foo = packed struct {
1982 \\ a: u8,
1983 \\ b: u32,
1984 \\};
1985 \\
1986 \\export fn entry() {
1987 \\ var foo = Foo { .a = 1, .b = 10 };
1988 \\ bar(&foo.b);
1989 \\}
1990 \\
1991 \\fn bar(x: &u32) {
1992 \\ *x += 1;
1993 \\}
1994 ,
1995 ".tmp_source.zig:8:13: error: expected type '&u32', found '&align 1 u32'");
1996
1997 cases.add("implicitly increasing slice alignment",
1998 \\const Foo = packed struct {
1999 \\ a: u8,
2000 \\ b: u32,
2001 \\};
2002 \\
2003 \\export fn entry() {
2004 \\ var foo = Foo { .a = 1, .b = 10 };
2005 \\ foo.b += 1;
2006 \\ bar((&foo.b)[0..1]);
2007 \\}
2008 \\
2009 \\fn bar(x: []u32) {
2010 \\ x[0] += 1;
2011 \\}
2012 ,
2013 ".tmp_source.zig:9:17: error: expected type '[]u32', found '[]align 1 u32'");
1979}2014}