diff options
| -rw-r--r-- | decl.c | 18 | ||||
| -rw-r--r-- | doc/c23.md | 7 | ||||
| -rw-r--r-- | expr.c | 10 | ||||
| -rw-r--r-- | qbe.c | 7 | ||||
| -rw-r--r-- | test/varargs+aarch64.qbe | 10 | ||||
| -rw-r--r-- | test/varargs+riscv64.qbe | 11 | ||||
| -rw-r--r-- | test/varargs+x86_64-sysv.c | 8 | ||||
| -rw-r--r-- | test/varargs+x86_64-sysv.qbe | 10 | 
8 files changed, 63 insertions, 18 deletions
@@ -604,20 +604,21 @@ declaratortypes(struct scope *s, struct list *result, char **name, struct scope  			t->u.func.nparam = 0;  			paramend = &t->u.func.params;  			s = mkscope(s); -			while (tok.kind != TRPAREN) { +			do { +				if (consume(TELLIPSIS)) { +					t->u.func.isvararg = true; +					break; +				} +				if (tok.kind == TRPAREN) +					break;  				d = parameter(s);  				if (d->name)  					scopeputdecl(s, d);  				*paramend = d;  				paramend = &d->next;  				++t->u.func.nparam; -				if (!consume(TCOMMA)) -					break; -				if (consume(TELLIPSIS)) { -					t->u.func.isvararg = true; -					break; -				} -			} +			} while (consume(TCOMMA)); +			expect(TRPAREN, "to close function declarator");  			if (funcscope && ptr->prev == prev) {  				/* we may need to re-open the scope later if this is a function definition */  				*funcscope = s; @@ -629,7 +630,6 @@ declaratortypes(struct scope *s, struct list *result, char **name, struct scope  				t->u.func.params = NULL;  				t->u.func.nparam = 0;  			} -			expect(TRPAREN, "to close function declarator");  			listinsert(ptr->prev, &t->link);  			allowattr = true;  			break; @@ -50,6 +50,12 @@ with `typeof` to specify that same type.  C23 also introduces `typeof_unqual`, which behaves the same as  `typeof` except that the specified type is unqualified. +## [N2975]: Relax requirements for variadic parameter lists + +C23 allows variadic functions with no named parameters. The second +argument to the va_arg macro is now optional and is only used for +backwards compatibility. +  ## [N3029]: Improved Normal Enumerations  C23 allows enumerators outside the range of `int`. When an enum @@ -79,5 +85,6 @@ used inside the enum.  [N2549]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2549.pdf  [N2900]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2900.htm  [N2927]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm +[N2975]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2975.pdf  [N3029]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3029.htm  [N3030]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3030.htm @@ -773,7 +773,7 @@ designator(struct scope *s, struct type *t, unsigned long long *offset)  static struct expr *  builtinfunc(struct scope *s, enum builtinkind kind)  { -	struct expr *e, *param; +	struct expr *e;  	struct type *t;  	struct member *m;  	char *name; @@ -868,12 +868,8 @@ builtinfunc(struct scope *s, enum builtinkind kind)  			error(&tok.loc, "va_start argument must have type va_list");  		if (typeadjvalist == targ->typevalist)  			e->base = mkunaryexpr(TBAND, e->base); -		expect(TCOMMA, "after va_list"); -		param = assignexpr(s); -		if (param->kind != EXPRIDENT) -			error(&tok.loc, "expected parameter identifier"); -		delexpr(param); -		/* XXX: check that this was actually a parameter name? */ +		if (consume(TCOMMA)) +			delexpr(assignexpr(s));  		break;  	default:  		fatal("internal error; unknown builtin"); @@ -1219,8 +1219,11 @@ emitfunc(struct func *f, bool global)  		putchar(' ');  		emitvalue(v);  	} -	if (f->type->u.func.isvararg) -		fputs(", ...", stdout); +	if (f->type->u.func.isvararg) { +		if (f->type->u.func.params) +			fputs(", ", stdout); +		fputs("...", stdout); +	}  	puts(") {");  	for (b = f->start; b; b = b->next) {  		emitvalue(&b->label); diff --git a/test/varargs+aarch64.qbe b/test/varargs+aarch64.qbe index 5b6e830..c444c85 100644 --- a/test/varargs+aarch64.qbe +++ b/test/varargs+aarch64.qbe @@ -45,3 +45,13 @@ function $f3(w %.1, ...) {  @while_join.9  	ret  } +export +function $f4(...) { +@start.10 +	%.1 =l alloc8 32 +@body.11 +	vastart %.1 +	%.2 =d vaarg %.1 +	%.3 =w vaarg %.1 +	ret +} diff --git a/test/varargs+riscv64.qbe b/test/varargs+riscv64.qbe index 48638bb..1b0851e 100644 --- a/test/varargs+riscv64.qbe +++ b/test/varargs+riscv64.qbe @@ -49,3 +49,14 @@ function $f3(w %.1, ...) {  	%.10 =l loadl %.3  	ret  } +export +function $f4(...) { +@start.10 +	%.1 =l alloc8 8 +@body.11 +	vastart %.1 +	%.2 =d vaarg %.1 +	%.3 =w vaarg %.1 +	%.4 =l loadl %.1 +	ret +} diff --git a/test/varargs+x86_64-sysv.c b/test/varargs+x86_64-sysv.c index 71bf1d3..dfa1b98 100644 --- a/test/varargs+x86_64-sysv.c +++ b/test/varargs+x86_64-sysv.c @@ -24,3 +24,11 @@ void f3(int n, ...) {  	}  	__builtin_va_end(ap);  } + +void f4(...) { +	__builtin_va_list ap; +	__builtin_va_start(ap); +	__builtin_va_arg(ap, double); +	__builtin_va_arg(ap, int); +	__builtin_va_end(ap); +} diff --git a/test/varargs+x86_64-sysv.qbe b/test/varargs+x86_64-sysv.qbe index 46904b6..4fa8e7b 100644 --- a/test/varargs+x86_64-sysv.qbe +++ b/test/varargs+x86_64-sysv.qbe @@ -47,3 +47,13 @@ function $f3(w %.1, ...) {  @while_join.9  	ret  } +export +function $f4(...) { +@start.10 +	%.1 =l alloc8 24 +@body.11 +	vastart %.1 +	%.2 =d vaarg %.1 +	%.3 =w vaarg %.1 +	ret +}  | 
