commit 40a039807d5241750fe54d5feac09ffda31f5e4f
parent a02c7e4fc2ca724738b578f9e1540d463079aa5a
Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
Date: Tue, 31 Mar 2026 09:32:18 +0200
cc1: Implement variadic macros
The code was checking for them but it didn't implement the __VA_ARGS__
parameter, so in practice they couldn't be used.
Diffstat:
4 files changed, 65 insertions(+), 19 deletions(-)
diff --git a/src/cmd/scc-cc/cc1/cc1.h b/src/cmd/scc-cc/cc1/cc1.h
@@ -112,7 +112,8 @@ enum {
SSTRING = 1 << 12,
STYPEDEF = 1 << 13,
SINITLST = 1 << 14,
- SHASINIT = 1 << 15
+ SHASINIT = 1 << 15,
+ SVARIADIC = 1 << 15,
};
/* node flags */
diff --git a/src/cmd/scc-cc/cc1/cpp.c b/src/cmd/scc-cc/cc1/cpp.c
@@ -144,7 +144,7 @@ unterminated:
}
static char *
-parameter(Macro *mp)
+parameter(Macro *mp, int n)
{
int siz;
char *s, *begin, *end;
@@ -164,8 +164,10 @@ parameter(Macro *mp)
appendpar(mp, input->p++, 1);
paren(mp);
break;
- case ')':
case ',':
+ if (n+1 == mp->npars)
+ goto append;
+ case ')':
begin = mp->arg;
end = begin + mp->argsiz;
@@ -184,6 +186,7 @@ parameter(Macro *mp)
goto unterminated;
continue;
default:
+ append:
appendpar(mp, input->p++, 1);
break;
}
@@ -214,10 +217,11 @@ parsepars(Macro *mp)
}
disexpand = 1;
- for (n = 0; n < NR_MACROARG; ++n) {
+ for (n = 0; n < NR_MACROARG; ) {
mp->arglist = xrealloc(mp->arglist, (n+1)*sizeof(char *));
- mp->arglist[n] = parameter(mp);
+ mp->arglist[n] = parameter(mp, n);
DBG("MACRO fetched arg '%s'", mp->arglist[n]);
+ n++;
c = *input->p++;
if (c == ')')
@@ -227,9 +231,16 @@ parsepars(Macro *mp)
}
disexpand = 0;
-checknpars:
- if (n+1 == mp->npars)
+ if (n == mp->npars)
+ return 1;
+
+ if (n == mp->npars-1 && mp->sym->flags & SVARIADIC) {
+ DBG("MACRO defaulted __VA_ARGS__ to \"\"");
+ mp->arglist = xrealloc(mp->arglist, (n+1)*sizeof(char *));
+ mp->arglist[n] = xstrdup("");
return 1;
+ }
+
error("macro \"%s\" received %d arguments, but it takes %d",
mp->sym->name, n, mp->npars);
}
@@ -521,21 +532,27 @@ getpars(Symbol *args[NR_MACROARG])
cpperror("too many parameters in macro");
return NR_MACROARG;
}
- if (accept(ELLIPSIS)) {
- args[n++] = NULL;
- break;
- }
- if (yytoken != IDEN) {
+
+ if (yytoken == ELLIPSIS) {
+ sym = newsym(NS_IDEN, "__VA_ARGS__");
+ } else if (yytoken == IDEN) {
+ sym = yylval.sym;
+ next();
+ } else {
cpperror("macro arguments must be identifiers");
return NR_MACROARG;
}
- if ((sym = install(NS_IDEN, yylval.sym)) == NULL) {
+
+ if ((sym = install(NS_IDEN, sym)) == NULL) {
errorp("duplicated macro parameter '%s'", yytext);
} else {
sym->flags |= SUSED;
args[n++] = sym;
}
- next();
+
+ if (accept(ELLIPSIS))
+ break;
+
} while (accept(','));
if (yytoken != ')') {
@@ -647,9 +664,10 @@ wrong_concat:
static void
define(void)
{
+ int n;
Symbol *sym,*args[NR_MACROARG];
char buff[LINESIZ+1];
- int n;
+ unsigned flags = SDECLARED|SSTRING;
if (cppoff)
return;
@@ -667,8 +685,8 @@ define(void)
namespace = NS_IDEN; /* Avoid polution in NS_CPP */
if ((n = getpars(args)) == NR_MACROARG)
goto delete;
- if (n > 0 && !args[n-1]) /* it is a variadic function */
- --n;
+ if (n > 0 && strcmp(args[n-1]->name, "__VA_ARGS__") == 0)
+ flags |= SVARIADIC;
sprintf(buff, "%02d#", n);
if (!getdefs(args, n, buff+3, LINESIZ-3))
@@ -680,7 +698,7 @@ define(void)
free(sym->u.s);
} else {
sym = install(NS_CPP, sym);
- sym->flags |= SDECLARED|SSTRING;
+ sym->flags |= flags;
}
sym->u.s = xstrdup(buff);
diff --git a/tests/cc/execute/0258-variadic.c b/tests/cc/execute/0258-variadic.c
@@ -0,0 +1,26 @@
+#define A(x,y) x+y
+#define B(x,y, ...) (x+y+ __VA_ARGS__ ## 0)
+#define C(x, ...) test(x, __VA_ARGS__)
+
+int
+test(int n1, int n2, int n3, int n4)
+{
+ return n1 + n2 + n3 + n4;
+}
+
+int
+main(void)
+{
+ int x = 3;
+
+ if (A(1,x) != 4)
+ return 1;
+ if (B(1,x) != 4)
+ return 2;
+ if (B(2,x,3) != 35)
+ return 3;
+ if (C(1, 2, 3, 4) != 10)
+ return 4;
+
+ return 0;
+}
diff --git a/tests/cc/execute/scc-tests.lst b/tests/cc/execute/scc-tests.lst
@@ -192,7 +192,7 @@
0199-voidpcast.c
0200-cpp.c [TODO]
0201-cpp.c
-0202-variadic.c [TODO]
+0202-variadic.c
0203-comment.c
0204-cast.c
0205-cpparg.c
@@ -248,3 +248,4 @@
0255-init.c
0256-ary.c
0257-main.c
+0258-variadic.c