From 19c263fd35d7a8dbae693c2f1b63e996748645d0 Mon Sep 17 00:00:00 2001 From: danielsan901998 Date: Thu, 27 Apr 2023 15:07:35 +0200 Subject: [PATCH 1/4] fix build and test for zig master --- build.zig | 6 +++--- deps/zig/type.zig | 1 + test/record_runner.zig | 2 +- test/runner.zig | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/build.zig b/build.zig index 8cacea8f..49bb3fa0 100644 --- a/build.zig +++ b/build.zig @@ -94,7 +94,7 @@ pub fn build(b: *Build) !void { if (link_libc) { exe.linkLibC(); } - exe.install(); + b.installArtifact(exe); const tests_step = b.step("test", "Run all tests"); tests_step.dependOn(&exe.step); @@ -112,7 +112,7 @@ pub fn build(b: *Build) !void { integration_tests.addOptions("build_options", test_runner_options); test_runner_options.addOption(bool, "test_all_allocation_failures", test_all_allocation_failures); - const integration_test_runner = integration_tests.run(); + const integration_test_runner = b.addRunArtifact(integration_tests); integration_test_runner.addArg(b.pathFromRoot("test/cases")); integration_test_runner.addArg(b.zig_exe); @@ -121,7 +121,7 @@ pub fn build(b: *Build) !void { .root_source_file = .{ .path = "test/record_runner.zig" }, }); record_tests.addModule("aro", aro_module); - const record_tests_runner = record_tests.run(); + const record_tests_runner = b.addRunArtifact(record_tests); record_tests_runner.addArg(b.pathFromRoot("test/records")); record_tests_runner.addArg(b.zig_exe); diff --git a/deps/zig/type.zig b/deps/zig/type.zig index 2c50aff2..bfd71636 100644 --- a/deps/zig/type.zig +++ b/deps/zig/type.zig @@ -372,6 +372,7 @@ pub const CType = enum { .renderscript32, .ve, .spu_2, + .xtensa, => 4, .aarch64_32, diff --git a/test/record_runner.zig b/test/record_runner.zig index 04f17958..db3d7eaf 100644 --- a/test/record_runner.zig +++ b/test/record_runner.zig @@ -63,7 +63,7 @@ pub fn main() !void { const alloc = fixed_alloc.allocator(); defer { gpa.free(fixed_buffer); - if (general_purpose_allocator.deinit()) std.process.exit(1); + if (general_purpose_allocator.deinit() == .leak) std.process.exit(1); } var args = try std.process.argsAlloc(gpa); diff --git a/test/runner.zig b/test/runner.zig index 56b0d4e5..01f49870 100644 --- a/test/runner.zig +++ b/test/runner.zig @@ -86,7 +86,7 @@ fn testAllAllocationFailures(cases: [][]const u8) !void { pub fn main() !void { const gpa = general_purpose_allocator.allocator(); - defer if (general_purpose_allocator.deinit()) std.process.exit(1); + defer if (general_purpose_allocator.deinit() == .leak) std.process.exit(1); var args = try std.process.argsAlloc(gpa); defer std.process.argsFree(gpa, args); From cb7c533342f329d2febb7adf125c1f4c7a8c661f Mon Sep 17 00:00:00 2001 From: danielsan901998 Date: Thu, 27 Apr 2023 15:08:15 +0200 Subject: [PATCH 2/4] Preprocessor: implement #elifdef and #elifndef --- src/Attribute.zig | 24 +++++++------ src/Diagnostics.zig | 16 +++++++++ src/Preprocessor.zig | 86 ++++++++++++++++++++++++++++++++++++++++++++ src/Tokenizer.zig | 12 +++++++ 4 files changed, 128 insertions(+), 10 deletions(-) diff --git a/src/Attribute.zig b/src/Attribute.zig index 1d9fef38..9565eb22 100644 --- a/src/Attribute.zig +++ b/src/Attribute.zig @@ -93,11 +93,13 @@ fn getArguments(comptime descriptor: type) []const ZigType.StructField { /// number of required arguments pub fn requiredArgCount(attr: Tag) u32 { switch (attr) { - inline else => |tag| comptime { - var needed = 0; - const fields = getArguments(@field(attributes, @tagName(tag))); - for (fields) |arg_field| { - if (!mem.eql(u8, arg_field.name, "__name_tok") and @typeInfo(arg_field.type) != .Optional) needed += 1; + inline else => |tag| { + comptime var needed = 0; + comptime { + const fields = getArguments(@field(attributes, @tagName(tag))); + for (fields) |arg_field| { + if (!mem.eql(u8, arg_field.name, "__name_tok") and @typeInfo(arg_field.type) != .Optional) needed += 1; + } } return needed; }, @@ -107,11 +109,13 @@ pub fn requiredArgCount(attr: Tag) u32 { /// maximum number of args that can be passed pub fn maxArgCount(attr: Tag) u32 { switch (attr) { - inline else => |tag| comptime { - const fields = getArguments(@field(attributes, @tagName(tag))); - var max = 0; - for (fields) |arg_field| { - if (!mem.eql(u8, arg_field.name, "__name_tok")) max += 1; + inline else => |tag| { + comptime var max = 0; + comptime { + const fields = getArguments(@field(attributes, @tagName(tag))); + for (fields) |arg_field| { + if (!mem.eql(u8, arg_field.name, "__name_tok")) max += 1; + } } return max; }, diff --git a/src/Diagnostics.zig b/src/Diagnostics.zig index 40267184..84ec5a1f 100644 --- a/src/Diagnostics.zig +++ b/src/Diagnostics.zig @@ -187,6 +187,22 @@ const messages = struct { const msg = "#elif after #else"; const kind = .@"error"; }; + const elifdef_without_if = struct { + const msg = "#elifdef without #if"; + const kind = .@"error"; + }; + const elifdef_after_else = struct { + const msg = "#elifdef after #else"; + const kind = .@"error"; + }; + const elifndef_without_if = struct { + const msg = "#elifndef without #if"; + const kind = .@"error"; + }; + const elifndef_after_else = struct { + const msg = "#elifndef after #else"; + const kind = .@"error"; + }; const else_without_if = struct { const msg = "#else without #if"; const kind = .@"error"; diff --git a/src/Preprocessor.zig b/src/Preprocessor.zig index 92ea6274..9528a449 100644 --- a/src/Preprocessor.zig +++ b/src/Preprocessor.zig @@ -365,6 +365,72 @@ fn preprocessExtra(pp: *Preprocessor, source: Source) MacroError!Token { else => unreachable, } }, + .keyword_elifdef => { + if (if_level == 0) { + try pp.err(directive, .elifdef_without_if); + if_level += 1; + if_kind.set(if_level, until_else); + } else if (if_level == 1) { + guard_name = null; + } + switch (if_kind.get(if_level)) { + until_else => { + const macro_name = (try pp.expectMacroName(&tokenizer)) orelse continue; + try pp.expectNl(&tokenizer); + if (pp.defines.get(macro_name) != null) { + if_kind.set(if_level, until_endif); + if (pp.verbose) { + pp.verboseLog(directive, "entering then branch of #elifdef", .{}); + } + } else { + if_kind.set(if_level, until_else); + try pp.skip(&tokenizer, .until_else); + if (pp.verbose) { + pp.verboseLog(directive, "entering else branch of #elifdef", .{}); + } + } + }, + until_endif => try pp.skip(&tokenizer, .until_endif), + until_endif_seen_else => { + try pp.err(directive, .elifdef_after_else); + skipToNl(&tokenizer); + }, + else => unreachable, + } + }, + .keyword_elifndef => { + if (if_level == 0) { + try pp.err(directive, .elifdef_without_if); + if_level += 1; + if_kind.set(if_level, until_else); + } else if (if_level == 1) { + guard_name = null; + } + switch (if_kind.get(if_level)) { + until_else => { + const macro_name = (try pp.expectMacroName(&tokenizer)) orelse continue; + try pp.expectNl(&tokenizer); + if (pp.defines.get(macro_name) == null) { + if_kind.set(if_level, until_endif); + if (pp.verbose) { + pp.verboseLog(directive, "entering then branch of #elifndef", .{}); + } + } else { + if_kind.set(if_level, until_else); + try pp.skip(&tokenizer, .until_else); + if (pp.verbose) { + pp.verboseLog(directive, "entering else branch of #elifndef", .{}); + } + } + }, + until_endif => try pp.skip(&tokenizer, .until_endif), + until_endif_seen_else => { + try pp.err(directive, .elifdef_after_else); + skipToNl(&tokenizer); + }, + else => unreachable, + } + }, .keyword_else => { try pp.expectNl(&tokenizer); if (if_level == 0) { @@ -812,6 +878,24 @@ fn skip( tokenizer.* = saved_tokenizer; return; }, + .keyword_elifdef => { + if (ifs_seen != 0 or cont == .until_endif) continue; + if (cont == .until_endif_seen_else) { + try pp.err(directive, .elifdef_after_else); + continue; + } + tokenizer.* = saved_tokenizer; + return; + }, + .keyword_elifndef => { + if (ifs_seen != 0 or cont == .until_endif) continue; + if (cont == .until_endif_seen_else) { + try pp.err(directive, .elifndef_after_else); + continue; + } + tokenizer.* = saved_tokenizer; + return; + }, .keyword_endif => { if (ifs_seen == 0) { tokenizer.* = saved_tokenizer; @@ -2452,6 +2536,8 @@ test "Include guards" { fn pairsWithIfndef(tok_id: RawToken.Id) bool { return switch (tok_id) { .keyword_elif, + .keyword_elifdef, + .keyword_elifndef, .keyword_else, => true, diff --git a/src/Tokenizer.zig b/src/Tokenizer.zig index 8bf00fcd..f145f1c7 100644 --- a/src/Tokenizer.zig +++ b/src/Tokenizer.zig @@ -209,6 +209,8 @@ pub const Token = struct { keyword_ifdef, keyword_ifndef, keyword_elif, + keyword_elifdef, + keyword_elifndef, keyword_endif, keyword_error, keyword_warning, @@ -292,6 +294,8 @@ pub const Token = struct { .keyword_ifdef, .keyword_ifndef, .keyword_elif, + .keyword_elifdef, + .keyword_elifndef, .keyword_endif, .keyword_error, .keyword_warning, @@ -422,6 +426,8 @@ pub const Token = struct { .keyword_ifdef, .keyword_ifndef, .keyword_elif, + .keyword_elifdef, + .keyword_elifndef, .keyword_endif, .keyword_error, .keyword_warning, @@ -601,6 +607,8 @@ pub const Token = struct { .keyword_ifdef => "ifdef", .keyword_ifndef => "ifndef", .keyword_elif => "elif", + .keyword_elifdef => "elifdef", + .keyword_elifndef => "elifndef", .keyword_endif => "endif", .keyword_error => "error", .keyword_warning => "warning", @@ -759,6 +767,8 @@ pub const Token = struct { .keyword_true, .keyword_false, .keyword_nullptr, + .keyword_elifdef, + .keyword_elifndef, => if (standard.atLeast(.c2x)) kw else .identifier, .keyword_int64, @@ -871,6 +881,8 @@ pub const Token = struct { .{ "ifdef", .keyword_ifdef }, .{ "ifndef", .keyword_ifndef }, .{ "elif", .keyword_elif }, + .{ "elifdef", .keyword_elifdef }, + .{ "elifndef", .keyword_elifndef }, .{ "endif", .keyword_endif }, .{ "error", .keyword_error }, .{ "warning", .keyword_warning }, From b7bade38f136225a9ad7924c612f5bc22bfd2567 Mon Sep 17 00:00:00 2001 From: danielsan901998 Date: Fri, 28 Apr 2023 12:23:03 +0200 Subject: [PATCH 3/4] add test for elifdef and elifndef --- test/cases/#elifdef.c | 17 +++++++++++++++++ test/cases/#elifdefc2x.c | 17 +++++++++++++++++ test/cases/expanded/#elifdef.c | 2 ++ test/cases/expanded/#elifdefc2x.c | 4 ++++ 4 files changed, 40 insertions(+) create mode 100644 test/cases/#elifdef.c create mode 100644 test/cases/#elifdefc2x.c create mode 100644 test/cases/expanded/#elifdef.c create mode 100644 test/cases/expanded/#elifdefc2x.c diff --git a/test/cases/#elifdef.c b/test/cases/#elifdef.c new file mode 100644 index 00000000..f1280f09 --- /dev/null +++ b/test/cases/#elifdef.c @@ -0,0 +1,17 @@ +//aro-args -E +#ifdef FOO +long long +#elifdef FOO +long +#elifndef FOO +int +#endif + +#define BAR +#ifdef FOO +long long +#elifdef BAR +long +#elifndef FOO +int +#endif diff --git a/test/cases/#elifdefc2x.c b/test/cases/#elifdefc2x.c new file mode 100644 index 00000000..6d81bf5d --- /dev/null +++ b/test/cases/#elifdefc2x.c @@ -0,0 +1,17 @@ +//aro-args -std=c2x -E +#ifdef FOO +long long +#elifdef FOO +long +#elifndef FOO +int +#endif + +#define BAR +#ifdef FOO +long long +#elifdef BAR +long +#elifndef FOO +int +#endif diff --git a/test/cases/expanded/#elifdef.c b/test/cases/expanded/#elifdef.c new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/test/cases/expanded/#elifdef.c @@ -0,0 +1,2 @@ + + diff --git a/test/cases/expanded/#elifdefc2x.c b/test/cases/expanded/#elifdefc2x.c new file mode 100644 index 00000000..65b237ce --- /dev/null +++ b/test/cases/expanded/#elifdefc2x.c @@ -0,0 +1,4 @@ + +int + +long From b18a02e76819c38fe9b71bceaeb3adeace11dc3c Mon Sep 17 00:00:00 2001 From: danielsan901998 Date: Fri, 28 Apr 2023 20:33:32 +0200 Subject: [PATCH 4/4] Preprocessor: enter else branch when missing macro name. --- src/Preprocessor.zig | 48 ++++++++++++++++--------- test/cases/#elifdefc2x_error.c | 20 +++++++++++ test/cases/expanded/#elifdefc2x_error.c | 4 +++ 3 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 test/cases/#elifdefc2x_error.c create mode 100644 test/cases/expanded/#elifdefc2x_error.c diff --git a/src/Preprocessor.zig b/src/Preprocessor.zig index 9528a449..4a6c5fe9 100644 --- a/src/Preprocessor.zig +++ b/src/Preprocessor.zig @@ -375,19 +375,27 @@ fn preprocessExtra(pp: *Preprocessor, source: Source) MacroError!Token { } switch (if_kind.get(if_level)) { until_else => { - const macro_name = (try pp.expectMacroName(&tokenizer)) orelse continue; - try pp.expectNl(&tokenizer); - if (pp.defines.get(macro_name) != null) { - if_kind.set(if_level, until_endif); - if (pp.verbose) { - pp.verboseLog(directive, "entering then branch of #elifdef", .{}); - } - } else { + const macro_name = try pp.expectMacroName(&tokenizer); + if (macro_name == null) { if_kind.set(if_level, until_else); try pp.skip(&tokenizer, .until_else); if (pp.verbose) { pp.verboseLog(directive, "entering else branch of #elifdef", .{}); } + } else { + try pp.expectNl(&tokenizer); + if (pp.defines.get(macro_name.?) != null) { + if_kind.set(if_level, until_endif); + if (pp.verbose) { + pp.verboseLog(directive, "entering then branch of #elifdef", .{}); + } + } else { + if_kind.set(if_level, until_else); + try pp.skip(&tokenizer, .until_else); + if (pp.verbose) { + pp.verboseLog(directive, "entering else branch of #elifdef", .{}); + } + } } }, until_endif => try pp.skip(&tokenizer, .until_endif), @@ -408,19 +416,27 @@ fn preprocessExtra(pp: *Preprocessor, source: Source) MacroError!Token { } switch (if_kind.get(if_level)) { until_else => { - const macro_name = (try pp.expectMacroName(&tokenizer)) orelse continue; - try pp.expectNl(&tokenizer); - if (pp.defines.get(macro_name) == null) { - if_kind.set(if_level, until_endif); - if (pp.verbose) { - pp.verboseLog(directive, "entering then branch of #elifndef", .{}); - } - } else { + const macro_name = try pp.expectMacroName(&tokenizer); + if (macro_name == null) { if_kind.set(if_level, until_else); try pp.skip(&tokenizer, .until_else); if (pp.verbose) { pp.verboseLog(directive, "entering else branch of #elifndef", .{}); } + } else { + try pp.expectNl(&tokenizer); + if (pp.defines.get(macro_name.?) == null) { + if_kind.set(if_level, until_endif); + if (pp.verbose) { + pp.verboseLog(directive, "entering then branch of #elifndef", .{}); + } + } else { + if_kind.set(if_level, until_else); + try pp.skip(&tokenizer, .until_else); + if (pp.verbose) { + pp.verboseLog(directive, "entering else branch of #elifndef", .{}); + } + } } }, until_endif => try pp.skip(&tokenizer, .until_endif), diff --git a/test/cases/#elifdefc2x_error.c b/test/cases/#elifdefc2x_error.c new file mode 100644 index 00000000..54b78fe3 --- /dev/null +++ b/test/cases/#elifdefc2x_error.c @@ -0,0 +1,20 @@ +//aro-args -E -std=c2x +#define EXPECTED_ERRORS \ + "#elifdefc2x_error.c:8:9: error: macro name missing" \ + "#elifdefc2x_error.c:17:10: error: macro name missing" +#ifdef FOO +long long +#elifdef +long +#else +int +#endif + +#define BAR +#ifdef FOO +long long +#elifndef +long +#else +int +#endif diff --git a/test/cases/expanded/#elifdefc2x_error.c b/test/cases/expanded/#elifdefc2x_error.c new file mode 100644 index 00000000..c5213969 --- /dev/null +++ b/test/cases/expanded/#elifdefc2x_error.c @@ -0,0 +1,4 @@ + +int + +int