From 82de1f088b2a13621158609b04ba9c97c473fe6f Mon Sep 17 00:00:00 2001 From: Evan Haas <evan@lagerdata.com> Date: Wed, 24 Apr 2024 23:55:14 -0700 Subject: [PATCH] Type: set incomplete array length correctly for typeof-types Fixes #692 --- src/aro/Parser.zig | 6 ++---- src/aro/Type.zig | 18 ++++++++++++++++++ test/cases/typeof incomplete array.c | 2 ++ 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 test/cases/typeof incomplete array.c diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index 8c971358..fc2afcc0 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -1818,10 +1818,8 @@ fn initDeclarator(p: *Parser, decl_spec: *DeclSpec, attr_buf_top: usize) Error!? var init_list_expr = try p.initializer(init_d.d.ty); init_d.initializer = init_list_expr; if (!init_list_expr.ty.isArray()) break :init; - if (init_d.d.ty.specifier == .incomplete_array) { - // Modifying .data is exceptionally allowed for .incomplete_array. - init_d.d.ty.data.array.len = init_list_expr.ty.arrayLen() orelse break :init; - init_d.d.ty.specifier = .array; + if (init_d.d.ty.is(.incomplete_array)) { + init_d.d.ty.setIncompleteArrayLen(init_list_expr.ty.arrayLen() orelse break :init); } } diff --git a/src/aro/Type.zig b/src/aro/Type.zig index dd983c8d..de9932ae 100644 --- a/src/aro/Type.zig +++ b/src/aro/Type.zig @@ -463,6 +463,24 @@ pub fn isArray(ty: Type) bool { }; } + +/// Must only be used to set the length of an incomplete array as determined by its initializer +pub fn setIncompleteArrayLen(ty: *Type, len: u64) void { + switch (ty.specifier) { + .incomplete_array => { + // Modifying .data is exceptionally allowed for .incomplete_array. + ty.data.array.len = len; + ty.specifier = .array; + }, + + .typeof_type => ty.data.sub_type.setIncompleteArrayLen(len), + .typeof_expr => ty.data.expr.ty.setIncompleteArrayLen(len), + .attributed => ty.data.attributed.base.setIncompleteArrayLen(len), + + else => unreachable, + } +} + /// Whether the type is promoted if used as a variadic argument or as an argument to a function with no prototype fn undergoesDefaultArgPromotion(ty: Type, comp: *const Compilation) bool { return switch (ty.specifier) { diff --git a/test/cases/typeof incomplete array.c b/test/cases/typeof incomplete array.c new file mode 100644 index 00000000..4cce1d4f --- /dev/null +++ b/test/cases/typeof incomplete array.c @@ -0,0 +1,2 @@ +typeof(const int[]) arr1 = {1,2}; +_Static_assert(sizeof(arr1) == sizeof(int[2]), "");