Simplify library usage
#define D ((sizeof(int) * 8 - 1) / (sizeof(int) * 8))
int a[D];
thread 40444 panic: access of inactive union field
/home/radomski/programs/rrc_values/arocc/src/Type.zig:549:102: 0x2b3e86 in .arocc.Type.elemType (rrc)
.pointer, .unspecified_variable_len_array, .decayed_unspecified_variable_len_array => ty.data.sub_type.*,
^
/home/radomski/programs/rrc_values/arocc/src/Type.zig:2001:40: 0x2b4a94 in .arocc.Type.printPrologue (rrc)
const elem_ty = ty.elemType();
^
/home/radomski/programs/rrc_values/arocc/src/Type.zig:1968:29: 0x2b4713 in .arocc.Type.print (rrc)
_ = try ty.printPrologue(mapper, w);
^
/home/radomski/programs/rrc_values/arocc/src/Type.zig:1987:32: 0x2b4983 in .arocc.Type.printPrologue (rrc)
try non_atomic_ty.print(mapper, w);
^
/home/radomski/programs/rrc_values/arocc/src/Type.zig:1968:29: 0x2b4713 in .arocc.Type.print (rrc)
_ = try ty.printPrologue(mapper, w);
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:363:16: 0x2b2705 in .arocc.Parser.typePairStrExtra (rrc)
try a.print(mapper, p.strings.writer());
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:354:30: 0x34b980 in .arocc.Parser.typePairStr (rrc)
return p.typePairStrExtra(a, " and ", b);
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:4579:64: 0x3498b0 in .arocc.Parser.Result.invalidBinTy (rrc)
try p.errStr(.invalid_bin_types, tok, try p.typePairStr(a.ty, b.ty));
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:4220:55: 0x31ced5 in .arocc.Parser.Result.adjustTypes (rrc)
if (kind == .arithmetic) return a.invalidBinTy(tok, b, p);
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:5348:32: 0x3acb20 in .arocc.Parser.mulExpr (rrc)
if (try lhs.adjustTypes(percent.?, &rhs, p, if (tag == .mod_expr) .integer else .arithmetic)) {
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:5304:28: 0x3aac06 in .arocc.Parser.addExpr (rrc)
var lhs = try p.mulExpr();
Related I think, because doing just:
int a[sizeof(int)];
thread 41922 panic: access of inactive union field
/home/radomski/programs/rrc_values/arocc/src/Type.zig:1917:108: 0x2eb9c2 in .arocc.Type.Builder.fromType (rrc)
.decayed_unspecified_variable_len_array => .{ .decayed_unspecified_variable_len_array = ty.data.sub_type },
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:344:30: 0x2c29c0 in .arocc.Parser.typeStr (rrc)
if (Type.Builder.fromType(ty).str()) |str| return str;
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:2505:70: 0x2f751a in .arocc.Parser.directDeclarator (rrc)
try p.errStr(.array_size_non_int, size_tok, try p.typeStr(size.ty));
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:2403:38: 0x2c201f in .arocc.Parser.declarator (rrc)
d.ty = try p.directDeclarator(d.ty, &d, kind);
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:1399:31: 0x2bfd32 in .arocc.Parser.initDeclarator (rrc)
.d = (try p.declarator(decl_spec.ty, .normal)) orelse return null,
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:746:39: 0x2bb0a1 in .arocc.Parser.decl (rrc)
var init_d = (try p.initDeclarator(&decl_spec, attr_buf_top)) orelse {
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:634:16: 0x28e9c4 in .arocc.Parser.parseOrNextDecl (rrc)
return func(p) catch |er| switch (er) {
^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:571:34: 0x274785 in .arocc.Parser.parse (rrc)
if (try p.parseOrNextDecl(decl)) continue;
^
/home/radomski/programs/rrc_values/src/main.zig:41:38: 0x26e4dc in main (rrc)
var tree = try arocc.Parser.parse(&pp);
^
/home/radomski/programs/rrc_values/zig/lib/std/start.zig:576:37: 0x24d343 in std.start.posixCallMainAndExit (rrc)
const result = root.main() catch |err| {
^
/home/radomski/programs/rrc_values/zig/lib/std/start.zig:338:5: 0x24d0d2 in std.start._start (rrc)
@call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
^
Are you using the latest master branch? And what command-line flags & platform for arocc are you using? Neither of those examples crashes for me, tested on MacOS and Linux.
Sory for the late response. I'm using arocc as a library and extract the AST from a given file. From what I can see is that invoking just the compiler on the provided examples does not reproduce the error, but using the compiler as a library reproduces the error every time.
I tried to create the smallest example that reproduces the issue.
const std = @import("std");
const arocc = @import("arocc");
pub fn main() !void {
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena_instance.deinit();
const arena = arena_instance.allocator();
var comp = arocc.Compilation.init(arena);
defer comp.deinit();
try comp.addDefaultPragmaHandlers();
try comp.include_dirs.append("/usr/include");
var file = try comp.addSourceFromBuffer("test.c", "int a[sizeof(int)];");
var pp = arocc.Preprocessor.init(&comp);
defer pp.deinit();
try pp.addBuiltinMacros();
const eof = pp.preprocess(file) catch |err| {
if (!std.unicode.utf8ValidateSlice(file.buf)) {
if (comp.diag.list.items.len > 0 and comp.diag.list.items[comp.diag.list.items.len - 1].tag == .invalid_utf8) {
return;
}
}
return err;
};
try pp.tokens.append(arena, eof);
var tree = try arocc.Parser.parse(&pp);
defer tree.deinit();
}
Commands issued
ateusz@DESKTOP-M8RDHEV e2v $ ./zig/zig build-exe repro.zig --pkg-begin arocc arocc/src/lib.zig --pkg-begin zig arocc/deps/zig/lib.zig --pkg-end --pkg-end
mateusz@DESKTOP-M8RDHEV e2v $ ./repro
thread 2510 panic: access of inactive union field
/home/mateusz/e2v/arocc/src/Type.zig:1917:108: 0x2cb8a2 in .arocc.Type.Builder.fromType (repro)
.decayed_unspecified_variable_len_array => .{ .decayed_unspecified_variable_len_array = ty.data.sub_type },
^
/home/mateusz/e2v/arocc/src/Parser.zig:344:30: 0x2acc50 in .arocc.Parser.typeStr (repro)
if (Type.Builder.fromType(ty).str()) |str| return str;
^
/home/mateusz/e2v/arocc/src/Parser.zig:2505:70: 0x2d756a in .arocc.Parser.directDeclarator (repro)
try p.errStr(.array_size_non_int, size_tok, try p.typeStr(size.ty));
^
/home/mateusz/e2v/arocc/src/Parser.zig:2403:38: 0x2ac2af in .arocc.Parser.declarator (repro)
d.ty = try p.directDeclarator(d.ty, &d, kind);
^
/home/mateusz/e2v/arocc/src/Parser.zig:1399:31: 0x2a9fc2 in .arocc.Parser.initDeclarator (repro)
.d = (try p.declarator(decl_spec.ty, .normal)) orelse return null,
^
/home/mateusz/e2v/arocc/src/Parser.zig:746:39: 0x2a5331 in .arocc.Parser.decl (repro)
var init_d = (try p.initDeclarator(&decl_spec, attr_buf_top)) orelse {
^
/home/mateusz/e2v/arocc/src/Parser.zig:634:16: 0x2853d4 in .arocc.Parser.parseOrNextDecl (repro)
return func(p) catch |er| switch (er) {
^
/home/mateusz/e2v/arocc/src/Parser.zig:571:34: 0x26c665 in .arocc.Parser.parse (repro)
if (try p.parseOrNextDecl(decl)) continue;
^
/home/mateusz/e2v/repro.zig:28:38: 0x2671f6 in main (repro)
var tree = try arocc.Parser.parse(&pp);
^
/home/mateusz/e2v/zig/lib/std/start.zig:576:37: 0x246023 in std.start.posixCallMainAndExit (repro)
const result = root.main() catch |err| {
^
/home/mateusz/e2v/zig/lib/std/start.zig:338:5: 0x245db2 in std.start._start (repro)
@call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
^
Aborted
mateusz@DESKTOP-M8RDHEV e2v $ ./zig/zig version
0.10.0-dev.3394+1a1b7a3af
mateusz@DESKTOP-M8RDHEV e2v $
The problem is that the compilation's built-in size type (size_t) was never generated, because you need to generate it via comp.generateBuiltinMacros. I can see how it's confusing since Compilation and Preprocessor have something that sounds like "built-in macros"; maybe that's an API sharp edge we can refine a little bit. Try this:
const std = @import("std");
const arocc = @import("arocc");
pub fn main() !void {
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena_instance.deinit();
const arena = arena_instance.allocator();
var comp = arocc.Compilation.init(arena);
defer comp.deinit();
try comp.addDefaultPragmaHandlers();
const builtin = try comp.generateBuiltinMacros(); // added this
try comp.include_dirs.append("/usr/include");
var file = try comp.addSourceFromBuffer("test.c", "int a[sizeof(int)];");
var pp = arocc.Preprocessor.init(&comp);
defer pp.deinit();
try pp.addBuiltinMacros();
_ = try pp.preprocess(builtin); // and this
const eof = pp.preprocess(file) catch |err| {
if (!std.unicode.utf8ValidateSlice(file.buf)) {
if (comp.diag.list.items.len > 0 and comp.diag.list.items[comp.diag.list.items.len - 1].tag == .invalid_utf8) {
return;
}
}
return err;
};
try pp.tokens.append(arena, eof);
var tree = try arocc.Parser.parse(&pp);
defer tree.deinit();
}
Yeah, that's much better. Thank you for your help :+)