mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
parent
2b92c5a23e
commit
2cd3989cb3
36
src/Sema.zig
36
src/Sema.zig
@ -24075,16 +24075,40 @@ fn coerceVarArgParam(
|
||||
inst: Air.Inst.Ref,
|
||||
inst_src: LazySrcLoc,
|
||||
) !Air.Inst.Ref {
|
||||
const inst_ty = sema.typeOf(inst);
|
||||
if (block.is_typeof) return inst;
|
||||
|
||||
switch (inst_ty.zigTypeTag()) {
|
||||
const coerced = switch (sema.typeOf(inst).zigTypeTag()) {
|
||||
// TODO consider casting to c_int/f64 if they fit
|
||||
.ComptimeInt, .ComptimeFloat => return sema.fail(block, inst_src, "integer and float literals in var args function must be casted", .{}),
|
||||
else => {},
|
||||
.ComptimeInt, .ComptimeFloat => return sema.fail(
|
||||
block,
|
||||
inst_src,
|
||||
"integer and float literals passed variadic function must be casted to a fixed-size number type",
|
||||
.{},
|
||||
),
|
||||
.Fn => blk: {
|
||||
const fn_val = try sema.resolveConstValue(block, .unneeded, inst, undefined);
|
||||
const fn_decl = fn_val.pointerDecl().?;
|
||||
break :blk try sema.analyzeDeclRef(fn_decl);
|
||||
},
|
||||
.Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
|
||||
else => inst,
|
||||
};
|
||||
|
||||
const coerced_ty = sema.typeOf(coerced);
|
||||
if (!sema.validateExternType(coerced_ty, .other)) {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
|
||||
const src_decl = sema.mod.declPtr(block.src_decl);
|
||||
try sema.explainWhyTypeIsNotExtern(msg, inst_src.toSrcLoc(src_decl), coerced_ty, .other);
|
||||
|
||||
try sema.addDeclaredHereNote(msg, coerced_ty);
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
// TODO implement more of this function.
|
||||
return inst;
|
||||
return coerced;
|
||||
}
|
||||
|
||||
// TODO migrate callsites to use storePtr2 instead.
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
extern fn printf([*:0]const u8, ...) c_int;
|
||||
|
||||
pub export fn entry() void {
|
||||
_ = printf("%d %d %d %d\n", 1, 2, 3, 4);
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :4:33: error: integer and float literals in var args function must be casted
|
||||
29
test/cases/compile_errors/variadic_arg_validation.zig
Normal file
29
test/cases/compile_errors/variadic_arg_validation.zig
Normal file
@ -0,0 +1,29 @@
|
||||
extern fn printf([*:0]const u8, ...) c_int;
|
||||
|
||||
pub export fn entry() void {
|
||||
_ = printf("%d %d %d %d\n", 1, 2, 3, 4);
|
||||
}
|
||||
|
||||
pub export fn entry1() void {
|
||||
var arr: [2]u8 = undefined;
|
||||
_ = printf("%d\n", arr);
|
||||
}
|
||||
|
||||
pub export fn entry2() void {
|
||||
_ = printf("%d\n", @as(u48, 2));
|
||||
}
|
||||
|
||||
pub export fn entry3() void {
|
||||
_ = printf("%d\n", {});
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :4:33: error: integer and float literals passed variadic function must be casted to a fixed-size number type
|
||||
// :9:24: error: arrays must be passed by reference to variadic function
|
||||
// :13:24: error: cannot pass 'u48' to variadic function
|
||||
// :13:24: note: only integers with power of two bits are extern compatible
|
||||
// :17:24: error: cannot pass 'void' to variadic function
|
||||
// :17:24: note: 'void' is a zero bit type; for C 'void' use 'anyopaque'
|
||||
@ -66,6 +66,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
|
||||
if (builtin.os.tag == .linux) {
|
||||
cases.addBuildFile("test/standalone/pie/build.zig", .{});
|
||||
}
|
||||
cases.addBuildFile("test/standalone/issue_12706/build.zig", .{});
|
||||
|
||||
// Ensure the development tools are buildable.
|
||||
|
||||
|
||||
39
test/standalone/issue_12706/build.zig
Normal file
39
test/standalone/issue_12706/build.zig
Normal file
@ -0,0 +1,39 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
|
||||
// TODO integrate this with the std.build executor API
|
||||
fn isRunnableTarget(t: CrossTarget) bool {
|
||||
if (t.isNative()) return true;
|
||||
|
||||
return (t.getOsTag() == builtin.os.tag and
|
||||
t.getCpuArch() == builtin.cpu.arch);
|
||||
}
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const exe = b.addExecutable("main", "main.zig");
|
||||
exe.setBuildMode(mode);
|
||||
exe.install();
|
||||
|
||||
const c_sources = [_][]const u8{
|
||||
"test.c",
|
||||
};
|
||||
|
||||
exe.addCSourceFiles(&c_sources, &.{});
|
||||
exe.linkLibC();
|
||||
|
||||
exe.setTarget(target);
|
||||
b.default_step.dependOn(&exe.step);
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
if (isRunnableTarget(target)) {
|
||||
const run_cmd = exe.run();
|
||||
test_step.dependOn(&run_cmd.step);
|
||||
} else {
|
||||
test_step.dependOn(&exe.step);
|
||||
}
|
||||
}
|
||||
12
test/standalone/issue_12706/main.zig
Normal file
12
test/standalone/issue_12706/main.zig
Normal file
@ -0,0 +1,12 @@
|
||||
const std = @import("std");
|
||||
extern fn testFnPtr(n: c_int, ...) void;
|
||||
|
||||
const val: c_int = 123;
|
||||
|
||||
fn func(a: c_int) callconv(.C) void {
|
||||
std.debug.assert(a == val);
|
||||
}
|
||||
|
||||
pub fn main() void {
|
||||
testFnPtr(2, func, val);
|
||||
}
|
||||
11
test/standalone/issue_12706/test.c
Normal file
11
test/standalone/issue_12706/test.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
void testFnPtr(int n, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, n);
|
||||
|
||||
void (*fnPtr)(int) = va_arg(ap, void (*)(int));
|
||||
int arg = va_arg(ap, int);
|
||||
fnPtr(arg);
|
||||
va_end(ap);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user