Commit 55e7c099ca

Veikka Tuominen <git@vexu.eu>
2021-09-20 20:05:42
stage2: various fixes to cImport, sizeOf and types to get tests passing
1 parent d64d5cf
src/AstGen.zig
@@ -7082,7 +7082,7 @@ fn builtinCall(
         .bit_cast   => return bitCast(  gz, scope, rl, node, params[0], params[1]),
         .TypeOf     => return typeOf(   gz, scope, rl, node, params),
         .union_init => return unionInit(gz, scope, rl, node, params),
-        .c_import   => return cImport(  gz, scope, rl, node, params[0]),
+        .c_import   => return cImport(  gz, scope,     node, params[0]),
 
         .@"export" => {
             const node_tags = tree.nodes.items(.tag);
@@ -7692,7 +7692,6 @@ fn shiftOp(
 fn cImport(
     gz: *GenZir,
     scope: *Scope,
-    rl: ResultLoc,
     node: Ast.Node.Index,
     body_node: Ast.Node.Index,
 ) InnerError!Zir.Inst.Ref {
@@ -7712,7 +7711,7 @@ fn cImport(
     try block_scope.setBlockBody(block_inst);
     try gz.instructions.append(gpa, block_inst);
 
-    return rvalue(gz, rl, .void_value, node);
+    return indexToRef(block_inst);
 }
 
 fn overflowArithmetic(
src/Compilation.zig
@@ -2644,7 +2644,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
 
         const dep_basename = std.fs.path.basename(out_dep_path);
         try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);
-        if (build_options.is_stage1) try comp.stage1_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);
+        if (build_options.is_stage1 and comp.bin_file.options.use_stage1) try comp.stage1_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);
 
         const digest = man.final();
         const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
src/print_zir.zig
@@ -407,15 +407,27 @@ const Writer = struct {
             .mul_with_saturation,
             .shl_with_saturation,
             => try self.writeSaturatingArithmetic(stream, extended),
+
             .struct_decl => try self.writeStructDecl(stream, extended),
             .union_decl => try self.writeUnionDecl(stream, extended),
             .enum_decl => try self.writeEnumDecl(stream, extended),
 
+            .c_undef, .c_include => {
+                const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
+                try self.writeInstRef(stream, inst_data.operand);
+                try stream.writeAll(") ");
+            },
+
+            .c_define => {
+                const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
+                try self.writeInstRef(stream, inst_data.lhs);
+                try stream.writeAll(", ");
+                try self.writeInstRef(stream, inst_data.rhs);
+                try stream.writeByte(')');
+            },
+
             .alloc,
             .builtin_extern,
-            .c_undef,
-            .c_include,
-            .c_define,
             .wasm_memory_size,
             .wasm_memory_grow,
             => try stream.writeAll("TODO))"),
src/Sema.zig
@@ -2183,11 +2183,10 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com
         @import("clang.zig").Stage2ErrorMsg.delete(c_import_res.errors.ptr, c_import_res.errors.len);
         return sema.mod.failWithOwnedErrorMsg(&child_block.base, msg);
     }
-    const c_import_pkg = @import("Package.zig").createWithDir(
+    const c_import_pkg = @import("Package.zig").create(
         sema.gpa,
-        sema.mod.comp.local_cache_directory,
         null,
-        std.fs.path.basename(c_import_res.out_zig_path),
+        c_import_res.out_zig_path,
     ) catch |err| switch (err) {
         error.OutOfMemory => return error.OutOfMemory,
         else => unreachable, // we pass null for root_src_dir_path
@@ -2200,6 +2199,9 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com
     const result = sema.mod.importPkg(c_import_pkg) catch |err|
         return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)});
 
+    sema.mod.astGenFile(result.file) catch |err|
+        return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)});
+
     try sema.mod.semaFile(result.file);
     const file_root_decl = result.file.root_decl.?;
     try sema.mod.declareDeclDependency(sema.owner_decl, file_root_decl);
@@ -6467,10 +6469,41 @@ fn runtimeBoolCmp(
 
 fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
     const inst_data = sema.code.instructions.items(.data)[inst].un_node;
+    const src = inst_data.src();
     const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
     const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
     const target = sema.mod.getTarget();
-    const abi_size = operand_ty.abiSize(target);
+    const abi_size = switch (operand_ty.zigTypeTag()) {
+        .Fn => unreachable,
+        .NoReturn,
+        .Undefined,
+        .Null,
+        .BoundFn,
+        .Opaque,
+        => return sema.mod.fail(&block.base, src, "no size available for type '{}'", .{operand_ty}),
+        .Type,
+        .EnumLiteral,
+        .ComptimeFloat,
+        .ComptimeInt,
+        .Void,
+        => 0,
+
+        .Bool,
+        .Int,
+        .Float,
+        .Pointer,
+        .Array,
+        .Struct,
+        .Optional,
+        .ErrorUnion,
+        .ErrorSet,
+        .Enum,
+        .Union,
+        .Vector,
+        .Frame,
+        .AnyFrame,
+        => operand_ty.abiSize(target),
+    };
     return sema.addIntUnsigned(Type.initTag(.comptime_int), abi_size);
 }
 
src/type.zig
@@ -602,8 +602,8 @@ pub const Type = extern union {
                 }
                 return false;
             },
+            .Float => return a.tag() == b.tag(),
             .Opaque,
-            .Float,
             .BoundFn,
             .Frame,
             => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),
test/behavior/sizeof_and_typeof.zig
@@ -10,118 +10,6 @@ test "@sizeOf and @TypeOf" {
 const x: u16 = 13;
 const z: @TypeOf(x) = 19;
 
-const A = struct {
-    a: u8,
-    b: u32,
-    c: u8,
-    d: u3,
-    e: u5,
-    f: u16,
-    g: u16,
-    h: u9,
-    i: u7,
-};
-
-const P = packed struct {
-    a: u8,
-    b: u32,
-    c: u8,
-    d: u3,
-    e: u5,
-    f: u16,
-    g: u16,
-    h: u9,
-    i: u7,
-};
-
-test "@offsetOf" {
-    // Packed structs have fixed memory layout
-    try expect(@offsetOf(P, "a") == 0);
-    try expect(@offsetOf(P, "b") == 1);
-    try expect(@offsetOf(P, "c") == 5);
-    try expect(@offsetOf(P, "d") == 6);
-    try expect(@offsetOf(P, "e") == 6);
-    try expect(@offsetOf(P, "f") == 7);
-    try expect(@offsetOf(P, "g") == 9);
-    try expect(@offsetOf(P, "h") == 11);
-    try expect(@offsetOf(P, "i") == 12);
-
-    // Normal struct fields can be moved/padded
-    var a: A = undefined;
-    try expect(@ptrToInt(&a.a) - @ptrToInt(&a) == @offsetOf(A, "a"));
-    try expect(@ptrToInt(&a.b) - @ptrToInt(&a) == @offsetOf(A, "b"));
-    try expect(@ptrToInt(&a.c) - @ptrToInt(&a) == @offsetOf(A, "c"));
-    try expect(@ptrToInt(&a.d) - @ptrToInt(&a) == @offsetOf(A, "d"));
-    try expect(@ptrToInt(&a.e) - @ptrToInt(&a) == @offsetOf(A, "e"));
-    try expect(@ptrToInt(&a.f) - @ptrToInt(&a) == @offsetOf(A, "f"));
-    try expect(@ptrToInt(&a.g) - @ptrToInt(&a) == @offsetOf(A, "g"));
-    try expect(@ptrToInt(&a.h) - @ptrToInt(&a) == @offsetOf(A, "h"));
-    try expect(@ptrToInt(&a.i) - @ptrToInt(&a) == @offsetOf(A, "i"));
-}
-
-test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" {
-    const p3a_len = 3;
-    const P3 = packed struct {
-        a: [p3a_len]u8,
-        b: usize,
-    };
-    try std.testing.expectEqual(0, @offsetOf(P3, "a"));
-    try std.testing.expectEqual(p3a_len, @offsetOf(P3, "b"));
-
-    const p5a_len = 5;
-    const P5 = packed struct {
-        a: [p5a_len]u8,
-        b: usize,
-    };
-    try std.testing.expectEqual(0, @offsetOf(P5, "a"));
-    try std.testing.expectEqual(p5a_len, @offsetOf(P5, "b"));
-
-    const p6a_len = 6;
-    const P6 = packed struct {
-        a: [p6a_len]u8,
-        b: usize,
-    };
-    try std.testing.expectEqual(0, @offsetOf(P6, "a"));
-    try std.testing.expectEqual(p6a_len, @offsetOf(P6, "b"));
-
-    const p7a_len = 7;
-    const P7 = packed struct {
-        a: [p7a_len]u8,
-        b: usize,
-    };
-    try std.testing.expectEqual(0, @offsetOf(P7, "a"));
-    try std.testing.expectEqual(p7a_len, @offsetOf(P7, "b"));
-
-    const p9a_len = 9;
-    const P9 = packed struct {
-        a: [p9a_len]u8,
-        b: usize,
-    };
-    try std.testing.expectEqual(0, @offsetOf(P9, "a"));
-    try std.testing.expectEqual(p9a_len, @offsetOf(P9, "b"));
-
-    // 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 25 etc. are further cases
-}
-
-test "@bitOffsetOf" {
-    // Packed structs have fixed memory layout
-    try expect(@bitOffsetOf(P, "a") == 0);
-    try expect(@bitOffsetOf(P, "b") == 8);
-    try expect(@bitOffsetOf(P, "c") == 40);
-    try expect(@bitOffsetOf(P, "d") == 48);
-    try expect(@bitOffsetOf(P, "e") == 51);
-    try expect(@bitOffsetOf(P, "f") == 56);
-    try expect(@bitOffsetOf(P, "g") == 72);
-
-    try expect(@offsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
-    try expect(@offsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
-    try expect(@offsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
-    try expect(@offsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
-    try expect(@offsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
-    try expect(@offsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
-    try expect(@offsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
-}
-
 test "@sizeOf on compile-time types" {
     try expect(@sizeOf(comptime_int) == 0);
     try expect(@sizeOf(comptime_float) == 0);
@@ -129,34 +17,6 @@ test "@sizeOf on compile-time types" {
     try expect(@sizeOf(@TypeOf(type)) == 0);
 }
 
-test "@sizeOf(T) == 0 doesn't force resolving struct size" {
-    const S = struct {
-        const Foo = struct {
-            y: if (@sizeOf(Foo) == 0) u64 else u32,
-        };
-        const Bar = struct {
-            x: i32,
-            y: if (0 == @sizeOf(Bar)) u64 else u32,
-        };
-    };
-
-    try expect(@sizeOf(S.Foo) == 4);
-    try expect(@sizeOf(S.Bar) == 8);
-}
-
-test "@TypeOf() has no runtime side effects" {
-    const S = struct {
-        fn foo(comptime T: type, ptr: *T) T {
-            ptr.* += 1;
-            return ptr.*;
-        }
-    };
-    var data: i32 = 0;
-    const T = @TypeOf(S.foo(i32, &data));
-    comptime try expect(T == i32);
-    try expect(data == 0);
-}
-
 test "@TypeOf() with multiple arguments" {
     {
         var var_1: u32 = undefined;
@@ -180,19 +40,6 @@ test "@TypeOf() with multiple arguments" {
     }
 }
 
-test "branching logic inside @TypeOf" {
-    const S = struct {
-        var data: i32 = 0;
-        fn foo() anyerror!i32 {
-            data += 1;
-            return undefined;
-        }
-    };
-    const T = @TypeOf(S.foo() catch undefined);
-    comptime try expect(T == i32);
-    try expect(S.data == 0);
-}
-
 fn fn1(alpha: bool) void {
     const n: usize = 7;
     _ = if (alpha) n else @sizeOf(usize);
@@ -201,64 +48,3 @@ fn fn1(alpha: bool) void {
 test "lazy @sizeOf result is checked for definedness" {
     _ = fn1;
 }
-
-test "@bitSizeOf" {
-    try expect(@bitSizeOf(u2) == 2);
-    try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);
-    try expect(@bitSizeOf(struct {
-        a: u2,
-    }) == 8);
-    try expect(@bitSizeOf(packed struct {
-        a: u2,
-    }) == 2);
-}
-
-test "@sizeOf comparison against zero" {
-    const S0 = struct {
-        f: *@This(),
-    };
-    const U0 = union {
-        f: *@This(),
-    };
-    const S1 = struct {
-        fn H(comptime T: type) type {
-            return struct {
-                x: T,
-            };
-        }
-        f0: H(*@This()),
-        f1: H(**@This()),
-        f2: H(***@This()),
-    };
-    const U1 = union {
-        fn H(comptime T: type) type {
-            return struct {
-                x: T,
-            };
-        }
-        f0: H(*@This()),
-        f1: H(**@This()),
-        f2: H(***@This()),
-    };
-    const S = struct {
-        fn doTheTest(comptime T: type, comptime result: bool) !void {
-            try expectEqual(result, @sizeOf(T) > 0);
-        }
-    };
-    // Zero-sized type
-    try S.doTheTest(u0, false);
-    try S.doTheTest(*u0, false);
-    // Non byte-sized type
-    try S.doTheTest(u1, true);
-    try S.doTheTest(*u1, true);
-    // Regular type
-    try S.doTheTest(u8, true);
-    try S.doTheTest(*u8, true);
-    try S.doTheTest(f32, true);
-    try S.doTheTest(*f32, true);
-    // Container with ptr pointing to themselves
-    try S.doTheTest(S0, true);
-    try S.doTheTest(U0, true);
-    try S.doTheTest(S1, true);
-    try S.doTheTest(U1, true);
-}
test/behavior/sizeof_and_typeof_stage1.zig
@@ -0,0 +1,218 @@
+const std = @import("std");
+const builtin = std.builtin;
+const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
+
+const A = struct {
+    a: u8,
+    b: u32,
+    c: u8,
+    d: u3,
+    e: u5,
+    f: u16,
+    g: u16,
+    h: u9,
+    i: u7,
+};
+
+const P = packed struct {
+    a: u8,
+    b: u32,
+    c: u8,
+    d: u3,
+    e: u5,
+    f: u16,
+    g: u16,
+    h: u9,
+    i: u7,
+};
+
+test "@offsetOf" {
+    // Packed structs have fixed memory layout
+    try expect(@offsetOf(P, "a") == 0);
+    try expect(@offsetOf(P, "b") == 1);
+    try expect(@offsetOf(P, "c") == 5);
+    try expect(@offsetOf(P, "d") == 6);
+    try expect(@offsetOf(P, "e") == 6);
+    try expect(@offsetOf(P, "f") == 7);
+    try expect(@offsetOf(P, "g") == 9);
+    try expect(@offsetOf(P, "h") == 11);
+    try expect(@offsetOf(P, "i") == 12);
+
+    // Normal struct fields can be moved/padded
+    var a: A = undefined;
+    try expect(@ptrToInt(&a.a) - @ptrToInt(&a) == @offsetOf(A, "a"));
+    try expect(@ptrToInt(&a.b) - @ptrToInt(&a) == @offsetOf(A, "b"));
+    try expect(@ptrToInt(&a.c) - @ptrToInt(&a) == @offsetOf(A, "c"));
+    try expect(@ptrToInt(&a.d) - @ptrToInt(&a) == @offsetOf(A, "d"));
+    try expect(@ptrToInt(&a.e) - @ptrToInt(&a) == @offsetOf(A, "e"));
+    try expect(@ptrToInt(&a.f) - @ptrToInt(&a) == @offsetOf(A, "f"));
+    try expect(@ptrToInt(&a.g) - @ptrToInt(&a) == @offsetOf(A, "g"));
+    try expect(@ptrToInt(&a.h) - @ptrToInt(&a) == @offsetOf(A, "h"));
+    try expect(@ptrToInt(&a.i) - @ptrToInt(&a) == @offsetOf(A, "i"));
+}
+
+test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" {
+    const p3a_len = 3;
+    const P3 = packed struct {
+        a: [p3a_len]u8,
+        b: usize,
+    };
+    try std.testing.expectEqual(0, @offsetOf(P3, "a"));
+    try std.testing.expectEqual(p3a_len, @offsetOf(P3, "b"));
+
+    const p5a_len = 5;
+    const P5 = packed struct {
+        a: [p5a_len]u8,
+        b: usize,
+    };
+    try std.testing.expectEqual(0, @offsetOf(P5, "a"));
+    try std.testing.expectEqual(p5a_len, @offsetOf(P5, "b"));
+
+    const p6a_len = 6;
+    const P6 = packed struct {
+        a: [p6a_len]u8,
+        b: usize,
+    };
+    try std.testing.expectEqual(0, @offsetOf(P6, "a"));
+    try std.testing.expectEqual(p6a_len, @offsetOf(P6, "b"));
+
+    const p7a_len = 7;
+    const P7 = packed struct {
+        a: [p7a_len]u8,
+        b: usize,
+    };
+    try std.testing.expectEqual(0, @offsetOf(P7, "a"));
+    try std.testing.expectEqual(p7a_len, @offsetOf(P7, "b"));
+
+    const p9a_len = 9;
+    const P9 = packed struct {
+        a: [p9a_len]u8,
+        b: usize,
+    };
+    try std.testing.expectEqual(0, @offsetOf(P9, "a"));
+    try std.testing.expectEqual(p9a_len, @offsetOf(P9, "b"));
+
+    // 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 25 etc. are further cases
+}
+
+test "@bitOffsetOf" {
+    // Packed structs have fixed memory layout
+    try expect(@bitOffsetOf(P, "a") == 0);
+    try expect(@bitOffsetOf(P, "b") == 8);
+    try expect(@bitOffsetOf(P, "c") == 40);
+    try expect(@bitOffsetOf(P, "d") == 48);
+    try expect(@bitOffsetOf(P, "e") == 51);
+    try expect(@bitOffsetOf(P, "f") == 56);
+    try expect(@bitOffsetOf(P, "g") == 72);
+
+    try expect(@offsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
+    try expect(@offsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
+    try expect(@offsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
+    try expect(@offsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
+    try expect(@offsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
+    try expect(@offsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
+    try expect(@offsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
+}
+
+test "@sizeOf(T) == 0 doesn't force resolving struct size" {
+    const S = struct {
+        const Foo = struct {
+            y: if (@sizeOf(Foo) == 0) u64 else u32,
+        };
+        const Bar = struct {
+            x: i32,
+            y: if (0 == @sizeOf(Bar)) u64 else u32,
+        };
+    };
+
+    try expect(@sizeOf(S.Foo) == 4);
+    try expect(@sizeOf(S.Bar) == 8);
+}
+
+test "@TypeOf() has no runtime side effects" {
+    const S = struct {
+        fn foo(comptime T: type, ptr: *T) T {
+            ptr.* += 1;
+            return ptr.*;
+        }
+    };
+    var data: i32 = 0;
+    const T = @TypeOf(S.foo(i32, &data));
+    comptime try expect(T == i32);
+    try expect(data == 0);
+}
+
+test "branching logic inside @TypeOf" {
+    const S = struct {
+        var data: i32 = 0;
+        fn foo() anyerror!i32 {
+            data += 1;
+            return undefined;
+        }
+    };
+    const T = @TypeOf(S.foo() catch undefined);
+    comptime try expect(T == i32);
+    try expect(S.data == 0);
+}
+
+test "@bitSizeOf" {
+    try expect(@bitSizeOf(u2) == 2);
+    try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);
+    try expect(@bitSizeOf(struct {
+        a: u2,
+    }) == 8);
+    try expect(@bitSizeOf(packed struct {
+        a: u2,
+    }) == 2);
+}
+
+test "@sizeOf comparison against zero" {
+    const S0 = struct {
+        f: *@This(),
+    };
+    const U0 = union {
+        f: *@This(),
+    };
+    const S1 = struct {
+        fn H(comptime T: type) type {
+            return struct {
+                x: T,
+            };
+        }
+        f0: H(*@This()),
+        f1: H(**@This()),
+        f2: H(***@This()),
+    };
+    const U1 = union {
+        fn H(comptime T: type) type {
+            return struct {
+                x: T,
+            };
+        }
+        f0: H(*@This()),
+        f1: H(**@This()),
+        f2: H(***@This()),
+    };
+    const S = struct {
+        fn doTheTest(comptime T: type, comptime result: bool) !void {
+            try expectEqual(result, @sizeOf(T) > 0);
+        }
+    };
+    // Zero-sized type
+    try S.doTheTest(u0, false);
+    try S.doTheTest(*u0, false);
+    // Non byte-sized type
+    try S.doTheTest(u1, true);
+    try S.doTheTest(*u1, true);
+    // Regular type
+    try S.doTheTest(u8, true);
+    try S.doTheTest(*u8, true);
+    try S.doTheTest(f32, true);
+    try S.doTheTest(*f32, true);
+    // Container with ptr pointing to themselves
+    try S.doTheTest(S0, true);
+    try S.doTheTest(U0, true);
+    try S.doTheTest(S1, true);
+    try S.doTheTest(U1, true);
+}
test/behavior/translate_c_macros.zig
@@ -3,28 +3,6 @@ const expectEqual = @import("std").testing.expectEqual;
 
 const h = @cImport(@cInclude("behavior/translate_c_macros.h"));
 
-test "initializer list expression" {
-    try expectEqual(h.Color{
-        .r = 200,
-        .g = 200,
-        .b = 200,
-        .a = 255,
-    }, h.LIGHTGRAY);
-}
-
-test "sizeof in macros" {
-    try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
-    try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
-}
-
-test "reference to a struct type" {
-    try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);
-}
-
-test "cast negative integer to pointer" {
-    try expectEqual(@intToPtr(?*c_void, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED);
-}
-
 test "casting to void with a macro" {
     h.IGNORE_ME_1(42);
     h.IGNORE_ME_2(42);
test/behavior/translate_c_macros_stage1.zig
@@ -0,0 +1,26 @@
+const expect = @import("std").testing.expect;
+const expectEqual = @import("std").testing.expectEqual;
+
+const h = @cImport(@cInclude("behavior/translate_c_macros.h"));
+
+test "initializer list expression" {
+    try expectEqual(h.Color{
+        .r = 200,
+        .g = 200,
+        .b = 200,
+        .a = 255,
+    }, h.LIGHTGRAY);
+}
+
+test "sizeof in macros" {
+    try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
+    try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
+}
+
+test "reference to a struct type" {
+    try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);
+}
+
+test "cast negative integer to pointer" {
+    try expectEqual(@intToPtr(?*c_void, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED);
+}
test/behavior.zig
@@ -11,6 +11,8 @@ test {
     _ = @import("behavior/array.zig");
     _ = @import("behavior/usingnamespace.zig");
     _ = @import("behavior/atomics.zig");
+    _ = @import("behavior/sizeof_and_typeof.zig");
+    _ = @import("behavior/translate_c_macros.zig");
 
     if (builtin.zig_is_stage2) {
         // When all comptime_memory.zig tests pass, #9646 can be closed.
@@ -128,7 +130,7 @@ test {
         _ = @import("behavior/saturating_arithmetic.zig");
         _ = @import("behavior/shuffle.zig");
         _ = @import("behavior/select.zig");
-        _ = @import("behavior/sizeof_and_typeof.zig");
+        _ = @import("behavior/sizeof_and_typeof_stage1.zig");
         _ = @import("behavior/slice.zig");
         _ = @import("behavior/slice_sentinel_comptime.zig");
         _ = @import("behavior/struct.zig");
@@ -157,6 +159,6 @@ test {
         _ = @import("behavior/while.zig");
         _ = @import("behavior/widening.zig");
         _ = @import("behavior/src.zig");
-        _ = @import("behavior/translate_c_macros.zig");
+        _ = @import("behavior/translate_c_macros_stage1.zig");
     }
 }