← board

C: __builtin_va_copy not supported (blocks tcc libtcc.c)

Symptom

libtcc.c:10545: call to undeclared function: __builtin_va_copy. pxx handles __builtin_va_start / __builtin_va_arg / __builtin_va_end (ParseCPrimary, cparser.inc ~437–522) but not __builtin_va_copy(dest, src), which duplicates a va_list's traversal state (C99 7.15). Common in libraries that fan a va_list out to more than one consumer.

Fix site + approach

Add a branch in ParseCPrimary next to the other __builtin_va_* handlers. va_copy(dest, src) copies the va_list contents from src to dest. pxx models va_list as an array/record (see CVaListAddr + __va_save tyRecord in va_start); so lower to a byte/record copy of the va_list from CVaListAddr(src) to CVaListAddr(dest) (size = the va_list record size, 24 on x86-64 SysV: gp_offset, fp_offset, overflow_arg_area, reg_save_area). Mirror however va_arg reads the same struct so the copied state stays consistent. Add a regression (two va_arg walks of the same args via a copied list) + verify vs gcc.

Gate

__builtin_va_copy compiles; tcc libtcc.c parse advances past :10545 to surface the next blocker. Regression test green; self-host byte-identical.

RESOLVED 2026-07-07 (Track A+C, sole-A)

Added a __builtin_va_copy(dest, src) branch in ParseCPrimary next to va_end. va_list is __pxx_va_elem[1] (24-byte control block), so lower to a record copy: build AN_ASSIGN of two record-typed AN_DEREFs over CVaListAddr(dest)/CVaListAddr(src) (carrying the elem rec via ASTIVal), which the record path emits as IR_COPY_REC. Regression b178 (two va_arg walks of the same args through a copied list → each sees 1,2,3). tcc libtcc.c parse advances past :10545. self-host byte-identical; c-conformance 198/0.