From f694cc443ccc17a494cd195151882ab5e491bbb2 Mon Sep 17 00:00:00 2001 From: _ov4 Date: Thu, 22 Oct 2026 13:59:48 +0000 Subject: feat(codegen): accept ^x of C values as variadic arguments In a variadic EXTERN position, ^x now passes the address of x as a plain pointer when x has a C type or is a C struct, like C's f(n, &x). The address of a pseudocode-typed value keeps the "must be a C value" error. Co-Authored-By: Claude Opus 5.5 --- lib/CodeGen/CallGen.cc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/CodeGen/CallGen.cc b/lib/CodeGen/CallGen.cc index 576520d..4631332 100644 --- a/lib/CodeGen/CallGen.cc +++ b/lib/CodeGen/CallGen.cc @@ -133,7 +133,10 @@ bool CodeGen::marshalCallArgs(const FuncSig &Signature, // C structs and pointers to them pass unchanged (C11 6.5.2.2p6-7, 7.16.1.1p2). Value *CodeGen::emitVariadicArgument(ExprAST *Expr, const std::string &Callee, size_t Position, const TypeInfo *&Promoted) { - const TypeInfo *Info = isWholeArrayVar(Expr) ? nullptr : getExprTypeInfo(Expr); + ExprAST *Target = Expr; + auto *Addr = dynamic_cast(Expr); + if (Addr) Target = Addr->getTarget(); + const TypeInfo *Info = isWholeArrayVar(Target) ? nullptr : getExprTypeInfo(Target); const TypeInfo *Record = Types->pointerBase(Info); std::string Why; if (Record && Record->isRecord() && !Record->IsClass && !Types->isCStruct(Record, &Why)) { @@ -145,6 +148,13 @@ Value *CodeGen::emitVariadicArgument(ExprAST *Expr, const std::string &Callee, s reportError("Variadic argument %zu to %s must be a C value; cast it to a C type", Position, Callee.c_str()); return nullptr; } + // ^x of a C value or C struct is a plain pointer, like C's f(n, &x). + if (Addr) { + LValueInfo LV; + if (!emitLValue(Target, LV)) return nullptr; + Promoted = Types->resolve("C_TYPE(\"void*\")"); + return LV.Addr; + } Promoted = Info; Value *V = emitExpr(Expr); if (!V || Info->Kind != TypeKind::CScalar) return V; -- cgit v1.3.1-4-g156e