diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index 5bcc7e01..b30f47a8 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -432,6 +432,11 @@ pub fn removeNull(p: *Parser, str: Value) !Value { } pub fn typeStr(p: *Parser, ty: Type) ![]const u8 { + if (@import("builtin").mode != .Debug) { + if (ty.is(.invalid)) { + return "Tried to render invalid type - this is an aro bug."; + } + } if (Type.Builder.fromType(ty).str(p.comp.langopts)) |str| return str; const strings_top = p.strings.items.len; defer p.strings.items.len = strings_top; @@ -446,6 +451,11 @@ pub fn typePairStr(p: *Parser, a: Type, b: Type) ![]const u8 { } pub fn typePairStrExtra(p: *Parser, a: Type, msg: []const u8, b: Type) ![]const u8 { + if (@import("builtin").mode != .Debug) { + if (a.is(.invalid) or b.is(.invalid)) { + return "Tried to render invalid type - this is an aro bug."; + } + } const strings_top = p.strings.items.len; defer p.strings.items.len = strings_top; @@ -635,7 +645,6 @@ fn diagnoseIncompleteDefinitions(p: *Parser) !void { const tys = node_slices.items(.ty); const data = node_slices.items(.data); - const err_start = p.comp.diagnostics.list.items.len; for (p.decl_buf.items) |decl_node| { const idx = @intFromEnum(decl_node); switch (tags[idx]) { @@ -656,8 +665,6 @@ fn diagnoseIncompleteDefinitions(p: *Parser) !void { try p.errStr(.tentative_definition_incomplete, tentative_def_tok, type_str); try p.errStr(.forward_declaration_here, data[idx].decl_ref, type_str); } - const errors_added = p.comp.diagnostics.list.items.len - err_start; - assert(errors_added == 2 * p.tentative_defs.count()); // Each tentative def should add an error + note } /// root : (decl | assembly ';' | staticAssert)* diff --git a/src/aro/Type.zig b/src/aro/Type.zig index 725cbeec..76c9a545 100644 --- a/src/aro/Type.zig +++ b/src/aro/Type.zig @@ -1056,7 +1056,7 @@ pub fn bitSizeof(ty: Type, comp: *const Compilation) ?u64 { } pub fn alignable(ty: Type) bool { - return ty.isArray() or !ty.hasIncompleteSize() or ty.is(.void); + return (ty.isArray() or !ty.hasIncompleteSize() or ty.is(.void)) and !ty.is(.invalid); } /// Get the alignment of a type diff --git a/test/cases/incomplete types.c b/test/cases/incomplete types.c index d0097f4f..755f6251 100644 --- a/test/cases/incomplete types.c +++ b/test/cases/incomplete types.c @@ -43,6 +43,12 @@ void incomplete_enum_float(void) { void incomplete_unspecified_variable_len_array(struct S b[1][*]); +void f1(struct Foo *a) { } /* should produce `warning: declaration of 'struct Foo' will not be visible outside of this function [-Wvisibility]` instead of tentative definition error */ + +struct Foo f; + +#define TESTS_SKIPPED 1 + #define EXPECTED_ERRORS "incomplete types.c:4:5: error: dereferencing pointer to incomplete type 'struct S'" \ "incomplete types.c:5:11: error: dereferencing pointer to incomplete type 'struct S'" \ "incomplete types.c:8:5: error: dereferencing pointer to incomplete type 'union U'" \ @@ -56,3 +62,8 @@ void incomplete_unspecified_variable_len_array(struct S b[1][*]); "incomplete types.c:34:13: error: statement requires expression with integer type ('struct node' invalid)" \ "incomplete types.c:40:12: error: variable has incomplete type 'enum E'" \ "incomplete types.c:44:58: error: array has incomplete element type 'struct S [*]'" \ + "incomplete types.c:48:12: error: tentative definition has type 'struct Foo' that is never completed" \ + "incomplete types.c:46:16: note: forward declaration of 'struct Foo'" \ + "incomplete types.c:48:12: error: tentative definition has type 'struct Foo' that is never completed" \ + "incomplete types.c:48:8: note: forward declaration of 'struct Foo'" \ +