diff --git a/src/Sema.zig b/src/Sema.zig index 2cd834862a..6feb679f4b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7253,7 +7253,15 @@ fn analyzeCall( }), .func => func_val.toIntern(), .ptr => |ptr| switch (ptr.addr) { - .decl => |decl| mod.declPtr(decl).val.toIntern(), + .decl => |decl| blk: { + const func_val_ptr = mod.declPtr(decl).val.toIntern(); + const intern_index = mod.intern_pool.indexToKey(func_val_ptr); + if (intern_index == .extern_func or (intern_index == .variable and intern_index.variable.is_extern)) + return sema.fail(block, call_src, "{s} call of extern function pointer", .{ + @as([]const u8, if (is_comptime_call) "comptime" else "inline"), + }); + break :blk func_val_ptr; + }, else => { assert(callee_ty.isPtrAtRuntime(mod)); return sema.fail(block, call_src, "{s} call of function pointer", .{ diff --git a/test/cases/compile_errors/invalid_extern_function_call.zig b/test/cases/compile_errors/invalid_extern_function_call.zig new file mode 100644 index 0000000000..640f68efb4 --- /dev/null +++ b/test/cases/compile_errors/invalid_extern_function_call.zig @@ -0,0 +1,16 @@ +const x = @extern(*const fn() callconv(.C) void, .{ .name = "foo" }); + +pub fn entry0() void { + comptime x(); +} + +pub fn entry1() void { + @call(.always_inline, x, .{}); +} + +// error +// backend=stage2 +// target=native +// +// :4:15: error: comptime call of extern function pointer +// :8:5: error: inline call of extern function pointer