fix(0128): foreign cstring returns + conflicting same-symbol bindings

Two genuine defects behind the 0128 filing (whose original repros were
both poisoned by binding getenv, which std already declares -> *u8):

1. Re-declaring a C symbol was silent first-wins: every call through
   the later declaration was typed by the older signature. Foreign
   registration now dedupes — equal signatures share one FuncId,
   conflicting ones are diagnosed.

2. Foreign -> string / -> ?string returns read garbage: C returns one
   char*, but the LLVM signature declared the fat {ptr,i64} (len =
   register garbage), and ?string was mis-declared SRET (the hidden
   out-pointer landed in the callee's first arg register). cstrRetKind
   now classifies such returns, declares them as plain ptr (never
   sret), and the call site synthesizes {ptr, strlen} via a
   branch-guarded strlen (NULL -> {null,0} / optional null), wrapping
   {string, i1} for ?string.

?[:0]u8 itself resolves fine (it is ?string); the spelling works in
return, param, local, and alias positions.

Regression: examples/1221 (plain + optional non-null + NULL paths) and
examples/1172 (conflict diagnostic); both FAIL pre-fix. The extern
dedupe collapses duplicate libc decls, so affected .ir snapshots were
regenerated. zig build test 426/426; run_examples 602/602;
distribution suite 21/21.
This commit is contained in:
agra
2026-06-12 14:13:01 +03:00
parent a8fbded567
commit d88bdd7242
50 changed files with 24903 additions and 28907 deletions

View File

@@ -192,7 +192,7 @@ declare i32 @mode_to_flags(ptr, i64) #0
declare i64 @open_file(ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @read_file(ptr sret({ { ptr, i64 }, i1 }), ptr, ptr) #0
declare ptr @read_file(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @write_file(ptr, ptr, ptr) #0
@@ -276,10 +276,10 @@ declare i32 @system(ptr) #0
declare void @run(ptr sret({ { i32, { ptr, i64 } }, i1 }), ptr, ptr) #0
; Function Attrs: nounwind
declare void @env(ptr sret({ { ptr, i64 }, i1 }), ptr, ptr) #0
declare ptr @env(ptr, ptr) #0
; Function Attrs: nounwind
declare void @find_executable(ptr sret({ { ptr, i64 }, i1 }), ptr, ptr) #0
declare ptr @find_executable(ptr, ptr) #0
; Function Attrs: nounwind
declare void @_exit(i32) #0
@@ -305,167 +305,131 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @read.3(i32, ptr, i64) #0
; Function Attrs: nounwind
declare i32 @close.4(i32) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.5(ptr, ptr, ptr, i64, i64, i64) #0
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
; Function Attrs: nounwind
declare ptr @CAllocator.alloc_bytes.6(ptr, ptr, i64) #0
declare ptr @CAllocator.alloc_bytes.4(ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @CAllocator.dealloc_bytes.7(ptr, ptr, ptr) #0
declare void @CAllocator.dealloc_bytes.5(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @GPA.init.8(ptr) #0
declare i64 @GPA.init.6(ptr) #0
; Function Attrs: nounwind
declare ptr @GPA.alloc_bytes.9(ptr, ptr, i64) #0
declare ptr @GPA.alloc_bytes.7(ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @GPA.dealloc_bytes.10(ptr, ptr, ptr) #0
declare void @GPA.dealloc_bytes.8(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.add_chunk.11(ptr, ptr, i64) #0
declare void @Arena.add_chunk.9(ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Arena.init.12(ptr sret({ ptr, i64, { ptr, ptr, ptr } }), ptr, ptr, i64) #0
declare void @Arena.init.10(ptr sret({ ptr, i64, { ptr, ptr, ptr } }), ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Arena.reset.13(ptr, ptr) #0
declare void @Arena.reset.11(ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.deinit.14(ptr, ptr) #0
declare void @Arena.deinit.12(ptr, ptr) #0
; Function Attrs: nounwind
declare ptr @Arena.alloc_bytes.15(ptr, ptr, i64) #0
declare ptr @Arena.alloc_bytes.13(ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Arena.dealloc_bytes.16(ptr, ptr, ptr) #0
declare void @Arena.dealloc_bytes.14(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @BufAlloc.init.17(ptr sret({ ptr, i64, i64 }), ptr, ptr, i64) #0
declare void @BufAlloc.init.15(ptr sret({ ptr, i64, i64 }), ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @BufAlloc.reset.18(ptr, ptr) #0
declare void @BufAlloc.reset.16(ptr, ptr) #0
; Function Attrs: nounwind
declare ptr @BufAlloc.alloc_bytes.19(ptr, ptr, i64) #0
declare ptr @BufAlloc.alloc_bytes.17(ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @BufAlloc.dealloc_bytes.20(ptr, ptr, ptr) #0
declare void @BufAlloc.dealloc_bytes.18(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @TrackingAllocator.init.21(ptr sret({ { ptr, ptr, ptr }, i64, i64, i64 }), ptr, ptr) #0
declare void @TrackingAllocator.init.19(ptr sret({ { ptr, ptr, ptr }, i64, i64, i64 }), ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @TrackingAllocator.leak_count.22(ptr, ptr) #0
declare i64 @TrackingAllocator.leak_count.20(ptr, ptr) #0
; Function Attrs: nounwind
declare void @TrackingAllocator.report.23(ptr, ptr) #0
declare void @TrackingAllocator.report.21(ptr, ptr) #0
; Function Attrs: nounwind
declare ptr @TrackingAllocator.alloc_bytes.24(ptr, ptr, i64) #0
declare ptr @TrackingAllocator.alloc_bytes.22(ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @TrackingAllocator.dealloc_bytes.25(ptr, ptr, ptr) #0
declare void @TrackingAllocator.dealloc_bytes.23(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @open.26(ptr, i32, ...) #0
declare i1 @File.is_valid.24(ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @close.27(i32) #0
declare i1 @File.close.25(ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @read.28(i32, ptr, i64) #0
declare i64 @File.read.26(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @lseek.29(i32, i64, i32) #0
declare i64 @File.write.27(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @unlink.30(ptr) #0
declare i64 @File.seek.28(ptr, ptr, i64, i64) #0
; Function Attrs: nounwind
declare i32 @rmdir.31(ptr) #0
declare i32 @mode_to_flags.29(ptr, i64) #0
; Function Attrs: nounwind
declare i32 @mkdir.32(ptr, i32) #0
declare i64 @open_file.30(ptr, ptr, i64) #0
; Function Attrs: nounwind
declare i32 @access.33(ptr, i32) #0
declare ptr @read_file.31(ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @chmod.34(ptr, i32) #0
declare i1 @write_file.32(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @rename.35(ptr, ptr) #0
declare i1 @append_file.33(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @File.is_valid.36(ptr, ptr) #0
declare i1 @exists.34(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @File.close.37(ptr, ptr) #0
declare i1 @delete_file.35(ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @File.read.38(ptr, ptr, ptr) #0
declare i1 @delete_dir.36(ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @File.write.39(ptr, ptr, ptr) #0
declare i1 @create_dir.37(ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @File.seek.40(ptr, ptr, i64, i64) #0
declare i1 @set_mode.38(ptr, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @mode_to_flags.41(ptr, i64) #0
declare i1 @move.39(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @open_file.42(ptr, ptr, i64) #0
declare i1 @create_dir_all.40(ptr, ptr) #0
; Function Attrs: nounwind
declare void @read_file.43(ptr sret({ { ptr, i64 }, i1 }), ptr, ptr) #0
declare i1 @copy_file.41(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @write_file.44(ptr, ptr, ptr) #0
declare ptr @basename.42(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @append_file.45(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @exists.46(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @delete_file.47(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @delete_dir.48(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @create_dir.49(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @set_mode.50(ptr, ptr, i32) #0
; Function Attrs: nounwind
declare i1 @move.51(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @create_dir_all.52(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @copy_file.53(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare ptr @basename.54(ptr, ptr) #0
; Function Attrs: nounwind
declare ptr @dirname.55(ptr, ptr) #0
declare ptr @dirname.43(ptr, ptr) #0
; Function Attrs: nounwind
declare void @Array.add(ptr, ptr, ptr, ptr) #0
@@ -666,64 +630,31 @@ declare ptr @BuildOptions.jni_main_java_source_at(i64, i64) #0
declare i64 @build_options() #0
; Function Attrs: nounwind
declare ptr @spaces.56(ptr, i32) #0
declare ptr @spaces.44(ptr, i32) #0
; Function Attrs: nounwind
declare i32 @sx_trace_len.57() #0
declare ptr @to_string.45(ptr) #0
; Function Attrs: nounwind
declare i32 @sx_trace_truncated.58() #0
declare void @print_current.46(ptr) #0
; Function Attrs: nounwind
declare i64 @sx_trace_frame_at.59(i32) #0
declare void @print_interpreter_frames.47(ptr) #0
; Function Attrs: nounwind
declare ptr @to_string.60(ptr) #0
declare void @run.48(ptr sret({ { i32, { ptr, i64 } }, i1 }), ptr, ptr) #0
; Function Attrs: nounwind
declare void @print_current.61(ptr) #0
declare ptr @env.49(ptr, ptr) #0
; Function Attrs: nounwind
declare void @print_interpreter_frames.62(ptr) #0
declare ptr @find_executable.50(ptr, ptr) #0
; Function Attrs: nounwind
declare ptr @popen.63(ptr, ptr) #0
declare void @exit.51(ptr, i8, ptr) #0
; Function Attrs: nounwind
declare i32 @pclose.64(ptr) #0
; Function Attrs: nounwind
declare i64 @fread.65(ptr, i64, i64, ptr) #0
; Function Attrs: nounwind
declare i32 @feof.66(ptr) #0
; Function Attrs: nounwind
declare ptr @getenv.67(ptr) #0
; Function Attrs: nounwind
declare i64 @strlen.68(ptr) #0
; Function Attrs: nounwind
declare i32 @system.69(ptr) #0
; Function Attrs: nounwind
declare void @run.70(ptr sret({ { i32, { ptr, i64 } }, i1 }), ptr, ptr) #0
; Function Attrs: nounwind
declare void @env.71(ptr sret({ { ptr, i64 }, i1 }), ptr, ptr) #0
; Function Attrs: nounwind
declare void @find_executable.72(ptr sret({ { ptr, i64 }, i1 }), ptr, ptr) #0
; Function Attrs: nounwind
declare void @_exit.73(i32) #0
; Function Attrs: nounwind
declare void @exit.74(ptr, i8, ptr) #0
; Function Attrs: nounwind
declare void @assert.75(ptr, i1, ptr, ptr) #0
declare void @assert.52(ptr, i1, ptr, ptr) #0
; Function Attrs: nounwind
declare ptr @_NSGetArgv() #0
@@ -753,97 +684,67 @@ declare ptr @Parsed.value_of(ptr, ptr, ptr) #0
declare i1 @is_long_flag(ptr, ptr) #0
; Function Attrs: nounwind
declare void @parse.76(ptr sret({ { { ptr, i64 }, { ptr, i64 }, i64, i1, { ptr, i64 }, { ptr, i64 }, [16 x { i1, { ptr, i64 } }] }, i32 }), ptr, ptr, ptr, ptr) #0
declare void @parse.53(ptr sret({ { { ptr, i64 }, { ptr, i64 }, i64, i1, { ptr, i64 }, { ptr, i64 }, [16 x { i1, { ptr, i64 } }] }, i32 }), ptr, ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @open.77(ptr, i32, ...) #0
declare i1 @File.is_valid.54(ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @close.78(i32) #0
declare i1 @File.close.55(ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @read.79(i32, ptr, i64) #0
declare i64 @File.read.56(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @lseek.80(i32, i64, i32) #0
declare i64 @File.write.57(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @unlink.81(ptr) #0
declare i64 @File.seek.58(ptr, ptr, i64, i64) #0
; Function Attrs: nounwind
declare i32 @rmdir.82(ptr) #0
declare i32 @mode_to_flags.59(ptr, i64) #0
; Function Attrs: nounwind
declare i32 @mkdir.83(ptr, i32) #0
declare i64 @open_file.60(ptr, ptr, i64) #0
; Function Attrs: nounwind
declare i32 @access.84(ptr, i32) #0
declare ptr @read_file.61(ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @chmod.85(ptr, i32) #0
declare i1 @write_file.62(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @rename.86(ptr, ptr) #0
declare i1 @append_file.63(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @File.is_valid.87(ptr, ptr) #0
declare i1 @exists.64(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @File.close.88(ptr, ptr) #0
declare i1 @delete_file.65(ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @File.read.89(ptr, ptr, ptr) #0
declare i1 @delete_dir.66(ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @File.write.90(ptr, ptr, ptr) #0
declare i1 @create_dir.67(ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @File.seek.91(ptr, ptr, i64, i64) #0
declare i1 @set_mode.68(ptr, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @mode_to_flags.92(ptr, i64) #0
declare i1 @move.69(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @open_file.93(ptr, ptr, i64) #0
declare i1 @create_dir_all.70(ptr, ptr) #0
; Function Attrs: nounwind
declare void @read_file.94(ptr sret({ { ptr, i64 }, i1 }), ptr, ptr) #0
declare i1 @copy_file.71(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @write_file.95(ptr, ptr, ptr) #0
declare ptr @basename.72(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @append_file.96(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @exists.97(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @delete_file.98(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @delete_dir.99(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @create_dir.100(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @set_mode.101(ptr, ptr, i32) #0
; Function Attrs: nounwind
declare i1 @move.102(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @create_dir_all.103(ptr, ptr) #0
; Function Attrs: nounwind
declare i1 @copy_file.104(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare ptr @basename.105(ptr, ptr) #0
; Function Attrs: nounwind
declare ptr @dirname.106(ptr, ptr) #0
declare ptr @dirname.73(ptr, ptr) #0
; Function Attrs: nounwind
declare i64 @rotr(ptr, i64, i64) #0
@@ -885,7 +786,7 @@ declare void @sha256_file(ptr sret({ [64 x i8], i1 }), ptr, ptr) #0
declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.107(ptr, i1) #0
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
define internal i64 @accept_c(ptr %0) #0 {