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.
16 lines
573 B
Plaintext
16 lines
573 B
Plaintext
// One C symbol bound twice with DIFFERENT sx signatures is diagnosed
|
|
// (issue 0128): the first registration used to silently win, mis-typing
|
|
// every call through the second declaration. Equal signatures share one
|
|
// registration silently (see std's read/write bound by several modules).
|
|
#import "modules/std.sx";
|
|
|
|
libc :: #library "c";
|
|
// std/process.sx already binds getenv as `-> *u8`; this view disagrees.
|
|
getenv_opt :: (name: [:0]u8) -> ?[:0]u8 #foreign libc "getenv";
|
|
|
|
main :: () -> i32 {
|
|
p := getenv_opt("PATH");
|
|
if p == null { return 1; }
|
|
return 0;
|
|
}
|