Commit e765495b11

Veikka Tuominen <git@vexu.eu>
2023-10-14 21:02:32
tests: translate-c and run-translated-c to the test harness
1 parent 58b07ea
lib/std/Build/Step/TranslateC.zig
@@ -17,12 +17,14 @@ target: CrossTarget,
 optimize: std.builtin.OptimizeMode,
 output_file: std.Build.GeneratedFile,
 link_libc: bool,
+use_clang: bool,
 
 pub const Options = struct {
     source_file: std.Build.LazyPath,
     target: CrossTarget,
     optimize: std.builtin.OptimizeMode,
     link_libc: bool = true,
+    use_clang: bool = true,
 };
 
 pub fn create(owner: *std.Build, options: Options) *TranslateC {
@@ -43,6 +45,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC {
         .optimize = options.optimize,
         .output_file = std.Build.GeneratedFile{ .step = &self.step },
         .link_libc = options.link_libc,
+        .use_clang = options.use_clang,
     };
     source.addStepDependencies(&self.step);
     return self;
@@ -130,6 +133,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
     if (self.link_libc) {
         try argv_list.append("-lc");
     }
+    if (!self.use_clang) {
+        try argv_list.append("-fno-clang");
+    }
 
     try argv_list.append("--listen=-");
 
test/cases/compile_errors/access_invalid_typeInfo_decl.zig
@@ -6,6 +6,6 @@ test "Crash" {
 // error
 // backend=stage2
 // target=native
-// is_test=1
+// is_test=true
 //
 // :1:11: error: use of undeclared identifier 'B'
test/cases/compile_errors/invalid_duplicate_test_decl_name.zig
@@ -4,7 +4,7 @@ test "thingy" {}
 // error
 // backend=stage2
 // target=native
-// is_test=1
+// is_test=true
 //
 // :1:6: error: duplicate test name: test.thingy
 // :2:6: note: other test here
test/cases/compile_errors/repeated_invalid_field_access_to_generic_function_returning_type_crashes_compiler_2655.zig
@@ -9,6 +9,6 @@ test "1" {
 // error
 // backend=stage2
 // target=native
-// is_test=1
+// is_test=true
 //
 // :2:12: error: use of undeclared identifier 'Q'
test/cases/compile_errors/return_invalid_type_from_test.zig
@@ -5,6 +5,6 @@ test "example" {
 // error
 // backend=stage2
 // target=native
-// is_test=1
+// is_test=true
 //
 // :2:12: error: expected type 'anyerror!void', found 'comptime_int'
test/cases/compile_errors/tagName_on_invalid_value_of_non-exhaustive_enum.zig
@@ -6,7 +6,7 @@ test "enum" {
 // error
 // backend=stage2
 // target=native
-// is_test=1
+// is_test=true
 //
 // :3:9: error: no field with value '@enumFromInt(5)' in enum 'test.enum.E'
 // :2:15: note: declared here
test/cases/llvm/hello_world.zig
@@ -7,7 +7,7 @@ pub fn main() void {
 // run
 // backend=llvm
 // target=x86_64-linux,x86_64-macos
-// link_libc=1
+// link_libc=true
 //
 // hello world!
 //
test/cases/run_translated_c/dereference address of.c
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+int main(void) {
+    int i = 0;
+    *&i = 42;
+    if (i != 42) abort();
+    return 0;
+}
+
+// run-translated-c
+// c_frontend=clang
+// link_libc=true
test/cases/translate_c/enums msvc.c
@@ -0,0 +1,16 @@
+enum Foo {
+    FooA = 2,
+    FooB = 5,
+    Foo1,
+};
+
+// translate-c
+// target=x86_64-windows-msvc
+// c_frontend=clang
+//
+// pub const FooA: c_int = 2;
+// pub const FooB: c_int = 5;
+// pub const Foo1: c_int = 6;
+// pub const enum_Foo = c_int;
+//
+// pub const Foo = enum_Foo;
test/cases/translate_c/enums.c
@@ -0,0 +1,16 @@
+enum Foo {
+    FooA = 2,
+    FooB = 5,
+    Foo1,
+};
+
+// translate-c
+// target=x86_64-linux
+// c_frontend=clang,aro
+//
+// pub const FooA: c_int = 2;
+// pub const FooB: c_int = 5;
+// pub const Foo1: c_int = 6;
+// pub const enum_Foo = c_uint;
+//
+// pub const Foo = enum_Foo;
test/cases/f32_passed_to_variadic_fn.zig
@@ -9,7 +9,7 @@ pub fn main() void {
 // run
 // backend=llvm
 // target=x86_64-linux-gnu
-// link_libc=1
+// link_libc=true
 //
 // f64: 2.000000
 // f32: 10.000000
test/cases/fn_typeinfo_passed_to_comptime_fn.zig
@@ -13,6 +13,6 @@ fn foo(comptime info: std.builtin.Type) !void {
 }
 
 // run
-// is_test=1
+// is_test=true
 // backend=llvm
 //
test/cases/README.md
@@ -9,7 +9,7 @@ If you want it to be run with `zig test` and match expected error messages:
 
 ```zig
 // error
-// is_test=1
+// is_test=true
 //
 // :4:13: error: 'try' outside function scope
 ```
@@ -22,6 +22,33 @@ This will do `zig run` on the code and expect exit code 0.
 // run
 ```
 
+## Translate-c
+
+If you want to test translating C code to Zig use `translate-c`:
+
+```c
+// translate-c
+// c_frontend=aro,clang
+// target=x86_64-linux
+//
+// pub const foo = 1;
+// pub const immediately_after_foo = 2;
+//
+// pub const somewhere_else_in_the_file = 3:
+```
+
+## Run Translated C
+
+If you want to test translating C code to Zig and then executing it use `run-translated-c`:
+
+```c
+// run-translated-c
+// c_frontend=aro,clang
+// target=x86_64-linux
+//
+// Hello world!
+```
+
 ## Incremental Compilation
 
 Make multiple files that have ".", and then an integer, before the ".zig"
test/cases/try_in_comptime_in_struct_in_test.zig
@@ -8,6 +8,6 @@ test "@unionInit on union w/ tag but no fields" {
 }
 
 // error
-// is_test=1
+// is_test=true
 //
 // :4:13: error: 'try' outside function scope
test/src/Cases.zig
@@ -1,6 +1,7 @@
 gpa: Allocator,
 arena: Allocator,
 cases: std.ArrayList(Case),
+translate: std.ArrayList(Translate),
 incremental_cases: std.ArrayList(IncrementalCase),
 
 pub const IncrementalCase = struct {
@@ -36,7 +37,7 @@ pub const Update = struct {
         Execution: []const u8,
         /// A header update compiles the input with the equivalent of
         /// `-femit-h` and tests the produced header against the
-        /// expected result
+        /// expected result.
         Header: []const u8,
     },
 
@@ -61,6 +62,11 @@ pub const Backend = enum {
     llvm,
 };
 
+pub const CFrontend = enum {
+    clang,
+    aro,
+};
+
 /// A `Case` consists of a list of `Update`. The same `Compilation` is used for each
 /// update, so each update's source is treated as a single file being
 /// updated by the test harness and incrementally compiled.
@@ -143,6 +149,25 @@ pub const Case = struct {
     }
 };
 
+pub const Translate = struct {
+    /// The name of the test case. This is shown if a test fails, and
+    /// otherwise ignored.
+    name: []const u8,
+
+    input: [:0]const u8,
+    target: CrossTarget,
+    link_libc: bool,
+    c_frontend: CFrontend,
+    kind: union(enum) {
+        /// Translate the input, run it and check that it
+        /// outputs the expected text.
+        run: []const u8,
+        /// Translate the input and check that it contains
+        /// the expected lines of code.
+        translate: []const []const u8,
+    },
+};
+
 pub fn addExe(
     ctx: *Cases,
     name: []const u8,
@@ -346,9 +371,12 @@ pub fn addCompile(
 pub fn addFromDir(ctx: *Cases, dir: std.fs.IterableDir) void {
     var current_file: []const u8 = "none";
     ctx.addFromDirInner(dir, &current_file) catch |err| {
-        std.debug.panic("test harness failed to process file '{s}': {s}\n", .{
-            current_file, @errorName(err),
-        });
+        std.debug.panicExtra(
+            @errorReturnTrace(),
+            @returnAddress(),
+            "test harness failed to process file '{s}': {s}\n",
+            .{ current_file, @errorName(err) },
+        );
     };
 }
 
@@ -395,10 +423,44 @@ fn addFromDirInner(
 
         const backends = try manifest.getConfigForKeyAlloc(ctx.arena, "backend", Backend);
         const targets = try manifest.getConfigForKeyAlloc(ctx.arena, "target", CrossTarget);
+        const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend);
         const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool);
         const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool);
         const output_mode = try manifest.getConfigForKeyAssertSingle("output_mode", std.builtin.OutputMode);
 
+        if (manifest.type == .translate_c) {
+            for (c_frontends) |c_frontend| {
+                for (targets) |target| {
+                    const output = try manifest.trailingLinesSplit(ctx.arena);
+                    try ctx.translate.append(.{
+                        .name = std.fs.path.stem(filename),
+                        .c_frontend = c_frontend,
+                        .target = target,
+                        .link_libc = link_libc,
+                        .input = src,
+                        .kind = .{ .translate = output },
+                    });
+                }
+            }
+            continue;
+        }
+        if (manifest.type == .run_translated_c) {
+            for (c_frontends) |c_frontend| {
+                for (targets) |target| {
+                    const output = try manifest.trailingSplit(ctx.arena);
+                    try ctx.translate.append(.{
+                        .name = std.fs.path.stem(filename),
+                        .c_frontend = c_frontend,
+                        .target = target,
+                        .link_libc = link_libc,
+                        .input = src,
+                        .kind = .{ .run = output },
+                    });
+                }
+            }
+            continue;
+        }
+
         var cases = std.ArrayList(usize).init(ctx.arena);
 
         // Cross-product to get all possible test combinations
@@ -439,21 +501,15 @@ fn addFromDirInner(
                     case.addCompile(src);
                 },
                 .@"error" => {
-                    const errors = try manifest.trailingAlloc(ctx.arena);
+                    const errors = try manifest.trailingLines(ctx.arena);
                     case.addError(src, errors);
                 },
                 .run => {
-                    var output = std.ArrayList(u8).init(ctx.arena);
-                    var trailing_it = manifest.trailing();
-                    while (trailing_it.next()) |line| {
-                        try output.appendSlice(line);
-                        try output.append('\n');
-                    }
-                    if (output.items.len > 0) {
-                        try output.resize(output.items.len - 1);
-                    }
-                    case.addCompareOutput(src, try output.toOwnedSlice());
+                    const output = try manifest.trailingSplit(ctx.arena);
+                    case.addCompareOutput(src, output);
                 },
+                .translate_c => @panic("c_frontend specified for compile case"),
+                .run_translated_c => @panic("c_frontend specified for compile case"),
                 .cli => @panic("TODO cli tests"),
             }
         }
@@ -468,6 +524,7 @@ pub fn init(gpa: Allocator, arena: Allocator) Cases {
     return .{
         .gpa = gpa,
         .cases = std.ArrayList(Case).init(gpa),
+        .translate = std.ArrayList(Translate).init(gpa),
         .incremental_cases = std.ArrayList(IncrementalCase).init(gpa),
         .arena = arena,
     };
@@ -482,7 +539,7 @@ pub fn lowerToBuildSteps(
     incremental_exe: *std.Build.Step.Compile,
 ) void {
     const host = std.zig.system.NativeTargetInfo.detect(.{}) catch |err|
-        std.debug.panic("unable to detect notive host: {s}\n", .{@errorName(err)});
+        std.debug.panic("unable to detect native host: {s}\n", .{@errorName(err)});
 
     for (self.incremental_cases.items) |incr_case| {
         if (true) {
@@ -589,7 +646,7 @@ pub fn lowerToBuildSteps(
             .Execution => |expected_stdout| no_exec: {
                 const run = if (case.target.ofmt == .c) run_step: {
                     const target_info = std.zig.system.NativeTargetInfo.detect(case.target) catch |err|
-                        std.debug.panic("unable to detect notive host: {s}\n", .{@errorName(err)});
+                        std.debug.panic("unable to detect target host: {s}\n", .{@errorName(err)});
                     if (host.getExternalExecutor(&target_info, .{ .link_libc = true }) != .native) {
                         // We wouldn't be able to run the compiled C code.
                         break :no_exec;
@@ -623,6 +680,68 @@ pub fn lowerToBuildSteps(
             .Header => @panic("TODO"),
         }
     }
+
+    for (self.translate.items) |*case| switch (case.kind) {
+        .run => |output| {
+            const annotated_case_name = b.fmt("run-translated-c  {s}", .{case.name});
+            if (opt_test_filter) |filter| {
+                if (std.mem.indexOf(u8, annotated_case_name, filter) == null) return;
+            }
+            if (!std.process.can_spawn) {
+                std.debug.print("Unable to spawn child processes on {s}, skipping test.\n", .{@tagName(builtin.os.tag)});
+                continue; // Pass test.
+            }
+
+            const target_info = std.zig.system.NativeTargetInfo.detect(case.target) catch |err|
+                std.debug.panic("unable to detect target host: {s}\n", .{@errorName(err)});
+            if (host.getExternalExecutor(&target_info, .{ .link_libc = true }) != .native) {
+                // We wouldn't be able to run the compiled C code.
+                continue; // Pass test.
+            }
+
+            const write_src = b.addWriteFiles();
+            const file_source = write_src.add("tmp.c", case.input);
+
+            const translate_c = b.addTranslateC(.{
+                .source_file = file_source,
+                .optimize = .Debug,
+                .target = case.target,
+                .link_libc = case.link_libc,
+                .use_clang = case.c_frontend == .clang,
+            });
+            translate_c.step.name = b.fmt("{s} translate-c", .{annotated_case_name});
+
+            const run_exe = translate_c.addExecutable(.{});
+            run_exe.step.name = b.fmt("{s} build-exe", .{annotated_case_name});
+            run_exe.linkLibC();
+            const run = b.addRunArtifact(run_exe);
+            run.step.name = b.fmt("{s} run", .{annotated_case_name});
+            run.expectStdOutEqual(output);
+
+            parent_step.dependOn(&run.step);
+        },
+        .translate => |output| {
+            const annotated_case_name = b.fmt("zig translate-c {s}", .{case.name});
+            if (opt_test_filter) |filter| {
+                if (std.mem.indexOf(u8, annotated_case_name, filter) == null) return;
+            }
+
+            const write_src = b.addWriteFiles();
+            const file_source = write_src.add("tmp.c", case.input);
+
+            const translate_c = b.addTranslateC(.{
+                .source_file = file_source,
+                .optimize = .Debug,
+                .target = case.target,
+                .link_libc = case.link_libc,
+                .use_clang = case.c_frontend == .clang,
+            });
+            translate_c.step.name = annotated_case_name;
+
+            const check_file = translate_c.addCheckFile(output);
+            parent_step.dependOn(&check_file.step);
+        },
+    };
 }
 
 /// Sort test filenames in-place, so that incremental test cases ("foo.0.zig",
@@ -780,7 +899,7 @@ const TestManifestConfigDefaults = struct {
         if (std.mem.eql(u8, key, "backend")) {
             return "stage2";
         } else if (std.mem.eql(u8, key, "target")) {
-            if (@"type" == .@"error") {
+            if (@"type" == .@"error" or @"type" == .translate_c or @"type" == .run_translated_c) {
                 return "native";
             }
             return comptime blk: {
@@ -807,12 +926,16 @@ const TestManifestConfigDefaults = struct {
                 .@"error" => "Obj",
                 .run => "Exe",
                 .compile => "Obj",
+                .translate_c => "Obj",
+                .run_translated_c => "Obj",
                 .cli => @panic("TODO test harness for CLI tests"),
             };
         } else if (std.mem.eql(u8, key, "is_test")) {
-            return "0";
+            return "false";
         } else if (std.mem.eql(u8, key, "link_libc")) {
-            return "0";
+            return "false";
+        } else if (std.mem.eql(u8, key, "c_frontend")) {
+            return "clang";
         } else unreachable;
     }
 };
@@ -844,6 +967,8 @@ const TestManifest = struct {
         run,
         cli,
         compile,
+        translate_c,
+        run_translated_c,
     };
 
     const TrailingIterator = struct {
@@ -912,6 +1037,10 @@ const TestManifest = struct {
                 break :blk .cli;
             } else if (std.mem.eql(u8, raw, "compile")) {
                 break :blk .compile;
+            } else if (std.mem.eql(u8, raw, "translate-c")) {
+                break :blk .translate_c;
+            } else if (std.mem.eql(u8, raw, "run-translated-c")) {
+                break :blk .run_translated_c;
             } else {
                 std.log.warn("unknown test case type requested: {s}", .{raw});
                 return error.UnknownTestCaseType;
@@ -979,7 +1108,21 @@ const TestManifest = struct {
         };
     }
 
-    fn trailingAlloc(self: TestManifest, allocator: Allocator) error{OutOfMemory}![]const []const u8 {
+    fn trailingSplit(self: TestManifest, allocator: Allocator) error{OutOfMemory}![]const u8 {
+        var out = std.ArrayList(u8).init(allocator);
+        defer out.deinit();
+        var trailing_it = self.trailing();
+        while (trailing_it.next()) |line| {
+            try out.appendSlice(line);
+            try out.append('\n');
+        }
+        if (out.items.len > 0) {
+            try out.resize(out.items.len - 1);
+        }
+        return try out.toOwnedSlice();
+    }
+
+    fn trailingLines(self: TestManifest, allocator: Allocator) error{OutOfMemory}![]const []const u8 {
         var out = std.ArrayList([]const u8).init(allocator);
         defer out.deinit();
         var it = self.trailing();
@@ -989,6 +1132,28 @@ const TestManifest = struct {
         return try out.toOwnedSlice();
     }
 
+    fn trailingLinesSplit(self: TestManifest, allocator: Allocator) error{OutOfMemory}![]const []const u8 {
+        // Collect output lines split by empty lines
+        var out = std.ArrayList([]const u8).init(allocator);
+        defer out.deinit();
+        var buf = std.ArrayList(u8).init(allocator);
+        defer buf.deinit();
+        var it = self.trailing();
+        while (it.next()) |line| {
+            if (line.len == 0) {
+                if (buf.items.len != 0) {
+                    try out.append(try buf.toOwnedSlice());
+                    buf.items.len = 0;
+                }
+                continue;
+            }
+            try buf.appendSlice(line);
+            try buf.append('\n');
+        }
+        try out.append(try buf.toOwnedSlice());
+        return try out.toOwnedSlice();
+    }
+
     fn ParseFn(comptime T: type) type {
         return fn ([]const u8) anyerror!T;
     }
@@ -1011,8 +1176,10 @@ const TestManifest = struct {
             }.parse,
             .Bool => return struct {
                 fn parse(str: []const u8) anyerror!T {
-                    const as_int = try std.fmt.parseInt(u1, str, 0);
-                    return as_int > 0;
+                    if (std.mem.eql(u8, str, "true")) return true;
+                    if (std.mem.eql(u8, str, "false")) return false;
+                    std.debug.print("{s}\n", .{str});
+                    return error.InvalidBool;
                 }
             }.parse,
             .Enum => return struct {
@@ -1124,9 +1291,47 @@ pub fn main() !void {
             if (cases.items.len == 0) {
                 const backends = try manifest.getConfigForKeyAlloc(arena, "backend", Backend);
                 const targets = try manifest.getConfigForKeyAlloc(arena, "target", CrossTarget);
+                const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend);
                 const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool);
+                const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool);
                 const output_mode = try manifest.getConfigForKeyAssertSingle("output_mode", std.builtin.OutputMode);
 
+                if (manifest.type == .translate_c) {
+                    for (c_frontends) |c_frontend| {
+                        for (targets) |target| {
+                            const output = try manifest.trailingLinesSplit(ctx.arena);
+                            try ctx.translate.append(.{
+                                .name = std.fs.path.stem(filename),
+                                .c_frontend = c_frontend,
+                                .target = target,
+                                .is_test = is_test,
+                                .link_libc = link_libc,
+                                .input = src,
+                                .kind = .{ .translate = output },
+                            });
+                        }
+                    }
+                    continue;
+                }
+                if (manifest.type == .run_translated_c) {
+                    for (c_frontends) |c_frontend| {
+                        for (targets) |target| {
+                            const output = try manifest.trailingSplit(ctx.arena);
+                            try ctx.translate.append(.{
+                                .name = std.fs.path.stem(filename),
+                                .c_frontend = c_frontend,
+                                .target = target,
+                                .is_test = is_test,
+                                .link_libc = link_libc,
+                                .output = output,
+                                .input = src,
+                                .kind = .{ .run = output },
+                            });
+                        }
+                    }
+                    continue;
+                }
+
                 // Cross-product to get all possible test combinations
                 for (backends) |backend| {
                     for (targets) |target| {
@@ -1158,7 +1363,7 @@ pub fn main() !void {
                         case.addCompile(src);
                     },
                     .@"error" => {
-                        const errors = try manifest.trailingAlloc(arena);
+                        const errors = try manifest.trailingLines(arena);
                         switch (strategy) {
                             .independent => {
                                 case.addError(src, errors);
@@ -1169,17 +1374,11 @@ pub fn main() !void {
                         }
                     },
                     .run => {
-                        var output = std.ArrayList(u8).init(arena);
-                        var trailing_it = manifest.trailing();
-                        while (trailing_it.next()) |line| {
-                            try output.appendSlice(line);
-                            try output.append('\n');
-                        }
-                        if (output.items.len > 0) {
-                            try output.resize(output.items.len - 1);
-                        }
-                        case.addCompareOutput(src, try output.toOwnedSlice());
+                        const output = try manifest.trailingSplit(ctx.arena);
+                        case.addCompareOutput(src, output);
                     },
+                    .translate_c => @panic("c_frontend specified for compile case"),
+                    .run_translated_c => @panic("c_frontend specified for compile case"),
                     .cli => @panic("TODO cli tests"),
                 }
             }
@@ -1255,6 +1454,11 @@ fn runCases(self: *Cases, zig_exe_path: []const u8) !void {
                 host,
             );
         }
+
+        for (self.translate.items) |*case| {
+            _ = case;
+            @panic("TODO is this even used?");
+        }
     }
 }
 
test/run_translated_c.zig
@@ -2,17 +2,14 @@ const std = @import("std");
 const tests = @import("tests.zig");
 const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n";
 
-pub fn addCases(cases: *tests.RunTranslatedCContext) void {
-    cases.add("dereference address of",
-        \\#include <stdlib.h>
-        \\int main(void) {
-        \\    int i = 0;
-        \\    *&i = 42;
-        \\    if (i != 42) abort();
-        \\	  return 0;
-        \\}
-    , "");
+// *********************************************************
+// *                                                       *
+// *               DO NOT ADD NEW CASES HERE               *
+// *   instead add a file to test/cases/run_translated_c   *
+// *                                                       *
+// *********************************************************
 
+pub fn addCases(cases: *tests.RunTranslatedCContext) void {
     cases.add("division of floating literals",
         \\#define _NO_CRT_STDIO_INLINE 1
         \\#include <stdio.h>
test/translate_c.zig
@@ -3,6 +3,13 @@ const builtin = @import("builtin");
 const tests = @import("tests.zig");
 const CrossTarget = std.zig.CrossTarget;
 
+// ********************************************************
+// *                                                      *
+// *               DO NOT ADD NEW CASES HERE              *
+// *     instead add a file to test/cases/translate_c     *
+// *                                                      *
+// ********************************************************
+
 pub fn addCases(cases: *tests.TranslateCContext) void {
     const default_enum_type = if (builtin.abi == .msvc) "c_int" else "c_uint";
 
@@ -3315,23 +3322,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\pub const FOO_CHAR = '\x3f';
     });
 
-    cases.add("enums",
-        \\enum Foo {
-        \\    FooA = 2,
-        \\    FooB = 5,
-        \\    Foo1,
-        \\};
-    , &[_][]const u8{
-        \\pub const FooA: c_int = 2;
-        \\pub const FooB: c_int = 5;
-        \\pub const Foo1: c_int = 6;
-        \\pub const enum_Foo =
-        ++ " " ++ default_enum_type ++
-            \\;
-        ,
-        \\pub const Foo = enum_Foo;
-    });
-
     cases.add("macro cast",
         \\#include <stdint.h>
         \\int baz(void *arg) { return 0; }