From 493cd034a97a01b0894c2ca585c5e3b19d8b9d01 Mon Sep 17 00:00:00 2001 From: drpriver Date: Thu, 10 Apr 2025 14:10:31 -0700 Subject: [PATCH] ImportC: va_arg fails in working C code (#21186) Fixes https://github.com/dlang/dmd/issues/20423 Ultimate cause of this issue was that va_arg was being shadowed by the collected template-like macros. As va_arg is not a normal function (it takes a type as a parameter), this interfered with the cparser's rewrite of va_arg to a call to the single argument template version in core.stdc.stdarg. --- compiler/src/dmd/cparse.d | 20 ++++++++++++++++---- compiler/test/compilable/test20423.c | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 compiler/test/compilable/test20423.c diff --git a/compiler/src/dmd/cparse.d b/compiler/src/dmd/cparse.d index 9ef2abc5eb..e852dfd4c2 100644 --- a/compiler/src/dmd/cparse.d +++ b/compiler/src/dmd/cparse.d @@ -6085,6 +6085,14 @@ final class CParser(AST) : Parser!AST } } + void nextLine() + { + // scan to end of line + while (*p) + ++p; + ++p; // advance to start of next line + } + while (p < endp) { //printf("|%s|\n", p); @@ -6096,6 +6104,13 @@ final class CParser(AST) : Parser!AST if (token.value == TOK.identifier) { auto id = token.ident; + // https://github.com/dlang/dmd/issues/20423 + // skip macros that could shadow special builtins + if (id == Id.va_arg) + { + nextLine(); + continue; + } const params = *p == '('; nextToken(); @@ -6341,10 +6356,7 @@ final class CParser(AST) : Parser!AST if (token.value == TOK.identifier) removeSym(token.ident); } - // scan to end of line - while (*p) - ++p; - ++p; // advance to start of next line + nextLine(); } if (newSymbols.length) diff --git a/compiler/test/compilable/test20423.c b/compiler/test/compilable/test20423.c new file mode 100644 index 0000000000..6311c2a5f1 --- /dev/null +++ b/compiler/test/compilable/test20423.c @@ -0,0 +1,18 @@ +// https://github.com/dlang/dmd/issues/20423 +#include +#include +#include + +void foo(double * pm, ...) { + va_list ap; + double * targ; + va_start(ap, pm); + for (int i=1; ; i++) { + va_arg(ap, int); + targ = va_arg(ap, double*); + if (targ == NULL) { + break; + } + } + va_end(ap); +}