From b0b195abd1c864d314648c534d2cee0ab6d14132 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 25 Mar 2026 16:42:20 +0300 Subject: [PATCH] cgen: fix incompatible types for redefinition of memcpy (fixes #14458) --- vlib/builtin/linux_bare/libc_impl.v | 18 +++++++++--------- vlib/builtin/wasm_bare/libc_impl.c.v | 18 +++++++++--------- vlib/v/gen/c/cheaders.v | 4 ++-- .../freestanding_net_const_memcpy.c.must_have | 6 ++++++ .../testdata/freestanding_net_const_memcpy.vv | 6 ++++++ vlib/v/help/build/build-c.txt | 8 ++++---- 6 files changed, 36 insertions(+), 24 deletions(-) create mode 100644 vlib/v/gen/c/testdata/freestanding_net_const_memcpy.c.must_have create mode 100644 vlib/v/gen/c/testdata/freestanding_net_const_memcpy.vv diff --git a/vlib/builtin/linux_bare/libc_impl.v b/vlib/builtin/linux_bare/libc_impl.v index 2de0e986d..7a1cc2a4e 100644 --- a/vlib/builtin/linux_bare/libc_impl.v +++ b/vlib/builtin/linux_bare/libc_impl.v @@ -6,9 +6,9 @@ __global global_allocator dlmalloc.Dlmalloc @[export: 'memcpy'] @[unsafe] -pub fn memcpy(dest voidptr, src voidptr, n usize) voidptr { +pub fn memcpy(dest voidptr, const_src voidptr, n usize) voidptr { dest_ := unsafe { &u8(dest) } - src_ := unsafe { &u8(src) } + src_ := unsafe { &u8(const_src) } unsafe { for i in 0 .. int(n) { dest_[i] = src_[i] @@ -25,8 +25,8 @@ fn __malloc(n usize) voidptr { @[export: 'strlen'] @[unsafe] -fn strlen(_s voidptr) usize { - s := unsafe { &u8(_s) } +fn strlen(const_s &char) usize { + s := unsafe { &u8(const_s) } mut i := 0 for ; unsafe { s[i] } != 0; i++ {} return usize(i) @@ -67,9 +67,9 @@ fn memset(s voidptr, c int, n usize) voidptr { @[export: 'memmove'] @[unsafe] -fn memmove(dest voidptr, src voidptr, n usize) voidptr { +fn memmove(dest voidptr, const_src voidptr, n usize) voidptr { dest_ := unsafe { &u8(dest) } - src_ := unsafe { &u8(src) } + src_ := unsafe { &u8(const_src) } mut temp_buf := unsafe { malloc(int(n)) } for i in 0 .. int(n) { unsafe { @@ -101,9 +101,9 @@ fn getchar() int { } @[export: 'memcmp'] -fn memcmp(a voidptr, b voidptr, n usize) int { - a_ := unsafe { &u8(a) } - b_ := unsafe { &u8(b) } +fn memcmp(const_a voidptr, const_b voidptr, n usize) int { + a_ := unsafe { &u8(const_a) } + b_ := unsafe { &u8(const_b) } for i in 0 .. int(n) { if unsafe { a_[i] != b_[i] } { unsafe { diff --git a/vlib/builtin/wasm_bare/libc_impl.c.v b/vlib/builtin/wasm_bare/libc_impl.c.v index 7b89d185b..6dbe357de 100644 --- a/vlib/builtin/wasm_bare/libc_impl.c.v +++ b/vlib/builtin/wasm_bare/libc_impl.c.v @@ -19,9 +19,9 @@ pub fn __malloc(size usize) voidptr { } @[unsafe] -pub fn memcpy(dest &C.void, src &C.void, n usize) &C.void { +pub fn memcpy(dest &C.void, const_src &C.void, n usize) &C.void { dest_ := unsafe { &u8(dest) } - src_ := unsafe { &u8(src) } + src_ := unsafe { &u8(const_src) } unsafe { for i in 0 .. int(n) { dest_[i] = src_[i] @@ -31,8 +31,8 @@ pub fn memcpy(dest &C.void, src &C.void, n usize) &C.void { } @[unsafe] -fn strlen(_s &C.void) usize { - s := unsafe { &u8(_s) } +fn strlen(const_s &char) usize { + s := unsafe { &u8(const_s) } mut i := 0 for ; unsafe { s[i] } != 0; i++ {} return usize(i) @@ -70,9 +70,9 @@ fn memset(s &C.void, c int, n usize) &C.void { } @[unsafe] -fn memmove(dest &C.void, src &C.void, n usize) &C.void { +fn memmove(dest &C.void, const_src &C.void, n usize) &C.void { dest_ := unsafe { &u8(dest) } - src_ := unsafe { &u8(src) } + src_ := unsafe { &u8(const_src) } mut temp_buf := unsafe { malloc(int(n)) } for i in 0 .. int(n) { unsafe { @@ -101,9 +101,9 @@ fn getchar() int { return 0 } -fn memcmp(a &C.void, b &C.void, n usize) int { - a_ := unsafe { &u8(a) } - b_ := unsafe { &u8(b) } +fn memcmp(const_a &C.void, const_b &C.void, n usize) int { + a_ := unsafe { &u8(const_a) } + b_ := unsafe { &u8(const_b) } for i in 0 .. int(n) { if unsafe { a_[i] != b_[i] } { unsafe { diff --git a/vlib/v/gen/c/cheaders.v b/vlib/v/gen/c/cheaders.v index 8319c78de..b690151c6 100644 --- a/vlib/v/gen/c/cheaders.v +++ b/vlib/v/gen/c/cheaders.v @@ -587,9 +587,9 @@ typedef long unsigned int size_t; void *malloc(size_t size); void *calloc(size_t nitems, size_t size); void *realloc(void *ptr, size_t size); -void *memcpy(void *dest, void *src, size_t n); +void *memcpy(void *dest, const void *src, size_t n); void *memset(void *s, int c, size_t n); -void *memmove(void *dest, void *src, size_t n); +void *memmove(void *dest, const void *src, size_t n); // varargs implementation, TODO: works on tcc and gcc, but is very unportable and hacky typedef __builtin_va_list va_list; #define va_start(a, b) __builtin_va_start(a, b) diff --git a/vlib/v/gen/c/testdata/freestanding_net_const_memcpy.c.must_have b/vlib/v/gen/c/testdata/freestanding_net_const_memcpy.c.must_have new file mode 100644 index 000000000..33271d135 --- /dev/null +++ b/vlib/v/gen/c/testdata/freestanding_net_const_memcpy.c.must_have @@ -0,0 +1,6 @@ +void *memcpy(void *dest, const void *src, size_t n); +void *memmove(void *dest, const void *src, size_t n); +VV_EXP voidptr memcpy(voidptr dest, const voidptr const_src, usize n); +VV_EXP usize strlen(const char* const_s); +VV_EXP voidptr memmove(voidptr dest, const voidptr const_src, usize n); +VV_EXP int memcmp(const voidptr const_a, const voidptr const_b, usize n); diff --git a/vlib/v/gen/c/testdata/freestanding_net_const_memcpy.vv b/vlib/v/gen/c/testdata/freestanding_net_const_memcpy.vv new file mode 100644 index 000000000..6e7455474 --- /dev/null +++ b/vlib/v/gen/c/testdata/freestanding_net_const_memcpy.vv @@ -0,0 +1,6 @@ +// vtest vflags: -freestanding +import net + +fn main() { + _ = net.AddrFamily.ip +} diff --git a/vlib/v/help/build/build-c.txt b/vlib/v/help/build/build-c.txt index 1b6e10b31..e98389c0f 100644 --- a/vlib/v/help/build/build-c.txt +++ b/vlib/v/help/build/build-c.txt @@ -95,14 +95,14 @@ see also `v help build`. @[export: 'calloc'] __calloc(nmemb usize, size usize) &C.void Like malloc, but sets all the bytes to `0` first. - memcpy(dest &C.void, src &C.void, n usize) &C.void + memcpy(dest &C.void, const_src &C.void, n usize) &C.void Moves n bytes from dest to src, and returns dest - memmove(dest &C.void, src &C.void, n usize) &C.void + memmove(dest &C.void, const_src &C.void, n usize) &C.void Like memcpy, but guaranteed to work if dest and src overlap. - memcmp(a &C.void, b &C.void, n usize) int + memcmp(const_a &C.void, const_b &C.void, n usize) int Compare two buffers of length n. If a and b are equal, return 0. Otherwise, return the difference between the first different letter. - strlen(s &C.void) usize + strlen(const_s &char) usize Returns the amount of bytes until the first `0`, starting at s memset(s &C.void, c int, n usize) &C.void Sets n bytes starting at s to c (c is casted to a char) -- 2.39.5