From 2516d8671faaaff7e8803a2025ba4891a6ae7c78 Mon Sep 17 00:00:00 2001 From: wrongnull Date: Mon, 1 May 2023 08:18:05 +0300 Subject: [PATCH] correct error note and check type of extern variables --- src/Sema.zig | 20 ++++++++++++++----- ...enum_without_explicit_integer_tag_type.zig | 2 +- .../extern_variable_has_non_extern_type.zig | 11 ++++++++++ ...h_non-extern_non-packed_enum_parameter.zig | 2 +- 4 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 test/cases/compile_errors/extern_variable_has_non_extern_type.zig diff --git a/src/Sema.zig b/src/Sema.zig index 1b55f765f99a1df6e61819c19b05e28fae79e32d..247dea5f6307c450e620faeb591996ebca1c8066 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -22986,10 +22986,20 @@ fn validateVarType( var_ty: Type, is_extern: bool, ) CompileError!void { + const mod = sema.mod; + if (is_extern and !try sema.validateExternType(var_ty, .other)) { + const msg = msg: { + const msg = try sema.errMsg(block, src, "extern variable cannot have type '{}'", .{var_ty.fmt(mod)}); + errdefer msg.destroy(sema.gpa); + const src_decl = mod.declPtr(block.src_decl); + try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), var_ty, .other); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(msg); + } + if (try sema.validateRunTimeType(var_ty, is_extern)) return; - const mod = sema.mod; - const msg = msg: { const msg = try sema.errMsg(block, src, "variable of type '{}' must be const or comptime", .{var_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); @@ -23295,10 +23305,10 @@ fn explainWhyTypeIsNotExtern( .Pointer => try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{}), .Void => try mod.errNoteNonLazy(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}), .NoReturn => try mod.errNoteNonLazy(src_loc, msg, "'noreturn' is only allowed as a return type", .{}), - .Int => if (ty.intInfo(sema.mod.getTarget()).bits > 128) { - try mod.errNoteNonLazy(src_loc, msg, "only integers with less than 128 bits are extern compatible", .{}); - } else { + .Int => if (!std.math.isPowerOfTwo(ty.intInfo(sema.mod.getTarget()).bits)) { try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{}); + } else { + try mod.errNoteNonLazy(src_loc, msg, "only integers with 8, 16, 32, 64 and 128 bits are extern compatible", .{}); }, .Fn => { if (position != .other) { diff --git a/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig b/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig index 606dda4b6e8b40c407d2a439106499b2690119e4..98a98f7e13e8ca5c23e5dd83f0cb47a8e8103cfa 100644 --- a/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig +++ b/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig @@ -14,5 +14,5 @@ comptime { // :3:5: error: unable to export type 'type' // :7:5: error: unable to export type 'tmp.E' // :7:5: note: enum tag type 'u1' is not extern compatible -// :7:5: note: only integers with power of two bits are extern compatible +// :7:5: note: only integers with 8, 16, 32, 64 and 128 bits are extern compatible // :1:11: note: enum declared here diff --git a/test/cases/compile_errors/extern_variable_has_non_extern_type.zig b/test/cases/compile_errors/extern_variable_has_non_extern_type.zig new file mode 100644 index 0000000000000000000000000000000000000000..a572e77c287b7a9f67c6add03025f23cde905718 --- /dev/null +++ b/test/cases/compile_errors/extern_variable_has_non_extern_type.zig @@ -0,0 +1,11 @@ +extern var foo: u3; +pub export fn entry() void { + _ = foo; +} + +// error +// backend=stage2 +// target=native +// +// :1:17: error: extern variable cannot have type 'u3' +// :1:17: note: only integers with power of two bits are extern compatible diff --git a/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig b/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig index 572378d09322f587a65d9bd955c866aabd633bf5..c6412161e53ac538d17547817661eabfb403994c 100644 --- a/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig +++ b/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig @@ -7,5 +7,5 @@ export fn entry(foo: Foo) void { _ = foo; } // // :2:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C' // :2:17: note: enum tag type 'u2' is not extern compatible -// :2:17: note: only integers with power of two bits are extern compatible +// :2:17: note: only integers with 8, 16, 32, 64 and 128 bits are extern compatible // :1:13: note: enum declared here -- 2.54.0