Commit be94299666

Andrew Kelley <superjoe30@gmail.com>
2017-08-29 21:19:15
prevent implicitly increasing pointer alignment
See #37
1 parent 8f682ef
Changed files (3)
src/analyze.cpp
@@ -2615,25 +2615,30 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *
         (!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const) &&
         (!actual_type->data.pointer.is_volatile || expected_type->data.pointer.is_volatile) &&
         actual_type->data.pointer.bit_offset == expected_type->data.pointer.bit_offset &&
-        actual_type->data.pointer.unaligned_bit_count == expected_type->data.pointer.unaligned_bit_count)
+        actual_type->data.pointer.unaligned_bit_count == expected_type->data.pointer.unaligned_bit_count &&
+        actual_type->data.pointer.alignment >= expected_type->data.pointer.alignment)
     {
         return types_match_const_cast_only(expected_type->data.pointer.child_type,
                 actual_type->data.pointer.child_type);
     }
 
-    // unknown size array const
+    // slice const
     if (expected_type->id == TypeTableEntryIdStruct &&
         actual_type->id == TypeTableEntryIdStruct &&
         expected_type->data.structure.is_slice &&
-        actual_type->data.structure.is_slice &&
-        (!actual_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
-          expected_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const) &&
-        (!actual_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_volatile ||
-          expected_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_volatile))
+        actual_type->data.structure.is_slice)
     {
-        return types_match_const_cast_only(
-                expected_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
-                actual_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type);
+        TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
+        TypeTableEntry *expected_ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry;
+        if ((!actual_ptr_type->data.pointer.is_const || expected_ptr_type->data.pointer.is_const) &&
+            (!actual_ptr_type->data.pointer.is_volatile || expected_ptr_type->data.pointer.is_volatile) &&
+            actual_ptr_type->data.pointer.bit_offset == expected_ptr_type->data.pointer.bit_offset &&
+            actual_ptr_type->data.pointer.unaligned_bit_count == expected_ptr_type->data.pointer.unaligned_bit_count &&
+            actual_ptr_type->data.pointer.alignment >= expected_ptr_type->data.pointer.alignment)
+        {
+            return types_match_const_cast_only(expected_ptr_type->data.pointer.child_type,
+                    actual_ptr_type->data.pointer.child_type);
+        }
     }
 
     // maybe
test/cases/align.zig
@@ -38,3 +38,18 @@ test "bit field alignment" {
 test "default alignment allows unspecified in type syntax" {
     assert(&u32 == &align @alignOf(u32) u32);
 }
+
+test "implicitly decreasing pointer alignment" {
+    const a: u32 align 4 = 3;
+    const b: u32 align 8 = 4;
+    assert(addUnaligned(&a, &b) == 7);
+}
+
+fn addUnaligned(a: &align 1 const u32, b: &align 1 const u32) -> u32 { *a + *b }
+
+test "implicitly decreasing slice alignment" {
+    const a: u32 align 4 = 3;
+    const b: u32 align 8 = 4;
+    assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7);
+}
+fn addUnalignedSlice(a: []align 1 const u32, b: []align 1 const u32) -> u32 { a[0] + b[0] }
test/compile_errors.zig
@@ -1976,4 +1976,39 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
         \\}
     ,
         ".tmp_source.zig:1:1: error: declaration shadows type 'u16'");
+
+    cases.add("implicitly increasing pointer alignment",
+        \\const Foo = packed struct {
+        \\    a: u8,
+        \\    b: u32,
+        \\};
+        \\
+        \\export fn entry() {
+        \\    var foo = Foo { .a = 1, .b = 10 };
+        \\    bar(&foo.b);
+        \\}
+        \\
+        \\fn bar(x: &u32) {
+        \\    *x += 1;
+        \\}
+    ,
+        ".tmp_source.zig:8:13: error: expected type '&u32', found '&align 1 u32'");
+
+    cases.add("implicitly increasing slice alignment",
+        \\const Foo = packed struct {
+        \\    a: u8,
+        \\    b: u32,
+        \\};
+        \\
+        \\export fn entry() {
+        \\    var foo = Foo { .a = 1, .b = 10 };
+        \\    foo.b += 1;
+        \\    bar((&foo.b)[0..1]);
+        \\}
+        \\
+        \\fn bar(x: []u32) {
+        \\    x[0] += 1;
+        \\}
+    ,
+        ".tmp_source.zig:9:17: error: expected type '[]u32', found '[]align 1 u32'");
 }