C: ternary with two string-literal arms segfaults at runtime
- Type: bug (Track C / shared
ir.incAN_TERNARY lowering). - Found: 2026-06-26 writing the printf engine (
upper ? "ABCDEF" : "abcdef").
Symptom
A cond ? "lit" : "lit" whose arms are string literals compiles "ok" but
segfaults when the value is used:
extern long write(int, const void *, unsigned long);
int main(void){
int u = 1;
const char *d = u ? "ABCDEF" : "abcdef";
write(1, d, 6); /* SIGSEGV */
return 0;
}
Cause
ir.inc AN_TERNARY lowering retags a tyString result arm to managed
tyAnsiString (so the per-arm assignment coerces the frozen literal into a
managed temp and the load yields a real handle). That is correct for Pascal's
managed-default string model, but in C mode a string literal is a frozen
char*/PChar, not a managed AnsiString — coercing it through the ARC assign
path produces a garbage handle that the consumer dereferences -> crash.
The lowering needs a CProgramMode branch: a C string-literal ternary arm must
carry the literal's address (char*) like the rest of the C string model, not
go through the managed-string temp.
Workaround in the meantime
Avoid string-literal ternary in C source; use if/else. lib/crtl/src/stdio.c
is written this way already.
Acceptance
The repro prints ABCDEF and exits 0.
DONE 2026-06-26 (Track A+C combined)
Fixed in ir.inc AN_TERNARY lowering: the tyString -> tyAnsiString retag now
has a CProgramMode branch — in C a string-literal arm is carried as a plain
tyPointer (the per-arm assign stores the literal's address, the load yields the
char*), only Pascal routes through the managed AnsiString temp. CProgramMode
gated, so Pascal self-compile is byte-identical. Both repros pass (0X,
ABCDEF). This was THE blocker for the entire crtl printf engine — stdio.c's
prefix = (k=='X') ? "0X" : "0x" (NOT actually avoided as this ticket claimed)
corrupted __crtl_vformat's frame, making snprintf re-enter ~7400x to stack
overflow. With it fixed, printf %d/%x/%s/%c/%p + width/precision all render ==
gcc. (Remaining printf gap: %f/%g = bug-c-double-vararg.)