Fix bug in code for varargs functions with multiple fixed parameters.

This was broken by the varargs changes in commit a20d69a211. The code was not accounting for the internal representation of the parameters being in reverse order, so it was basing address calculations on the first fixed parameter rather than the last one, resulting in the wrong number of bytes being removed from the stack (generally causing a crash).

This affected the c99stdio.c test case, and is now also covered in c99stdarg.c.
This commit is contained in:
Stephen Heumann 2022-01-01 22:42:42 -06:00
parent 45fad90d6d
commit ed3035cb99
2 changed files with 20 additions and 8 deletions

View File

@ -967,10 +967,10 @@ var
size: integer; {size of the parameter}
sp: identPtr; {symbol pointer}
tk: tokenType; {symbol name token}
first: boolean; {first iteration of loop over params?}
begin {GenParameters}
pln := 0;
size := 0;
first := true;
if pp <> nil then begin {prototyped parameters}
tk.kind := ident;
tk.numString := nil;
@ -993,6 +993,11 @@ if pp <> nil then begin {prototyped parameters}
Gen3(dc_prm, pln, size, sp^.pdisp);
end; {else}
sp^.pln := pln;
if first then begin
first := false;
lastParameterLLN := pln;
lastParameterSize := size;
end; {if}
pp := pp^.next;
end; {while}
end {if}
@ -1013,13 +1018,20 @@ else begin {K&R parameters}
size := 2;
Gen3(dc_prm, sp^.lln, size, sp^.pdisp);
end; {else}
if first then begin
first := false;
lastParameterLLN := pln;
lastParameterSize := size;
end; {if}
end; {if}
sp := sp^.next;
end; {while}
end; {for}
if first then begin
lastParameterLLN := 0;
lastParameterSize := 0;
end; {if}
end; {else}
lastParameterLLN := pln;
lastParameterSize := size;
end; {GenParameters}

View File

@ -22,12 +22,12 @@ int va_list_fn(va_list ap) {
return 1;
}
int va_fn(int x, ...) {
int va_fn(int x, int y, int z, ...) {
va_list ap, ap2;
int i, *ip = &i;
/* Test basic varargs functionality */
va_start(ap, x);
va_start(ap, z);
if (va_arg(ap, int) != 12345)
return 0;
@ -46,7 +46,7 @@ int va_fn(int x, ...) {
va_end(ap2);
/* Test that varargs processing can be restarted */
va_start(ap, x);
va_start(ap, z);
if (va_arg(ap, int) != 12345)
return 0;
va_end(ap);
@ -60,7 +60,7 @@ int va_fn(int x, ...) {
int main(void) {
if (!va_fn(1, 12345, 67890.0, 1234567890L))
if (!va_fn(1, 2, 3, 12345, 67890.0, 1234567890L))
goto Fail;
printf ("Passed Conformance Test c99stdarg\n");