[gnu.gcc.bug] Variable argument lists in GCC

dave@UUNET.UU.NET (Speaker-To-Animals) (02/01/89)

I have noticed a change in gcc's stdarg implementation.  I'm not
sure if it's a bug, but my program no longer works.  I first noticed
the change with version 1.31 of the compiler, although I believe the
change was made in an earlier version.  The problem is shown by the
following program:

#include	<stdarg.h>

void fred(int, ...);
void jim(va_list);

void
main()
{

	fred(1, 2, 3);

}

void
fred(int i, ...)
{
	va_list ap;
	
	va_start(ap, i);
	jim(ap);
	printf("FRED %d\n", va_arg(ap, int));
	va_end(ap);

}

void
jim(va_list ap)
{

	printf("JIM %d\n", va_arg(ap, int));

}
	       

When run with the stdarg.h file supplied with version 1.31 of gcc,
the output is:

JIM 2
FRED 2

An older version of stdarg.h - sorry, I can't find the original version
number - produced:

JIM 2
FRED 3

Obviously, the newer version does not `remember' the calls made to
va_arg() after the argument pointer has been passed to other functions.
The older implementation had definitions like:

typedef char *va_list[1];
#define va_start(AP, LASTARG)                                           \
 (AP[0] = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))

instead of

typedef char *va_list;
#define va_start(AP, LASTARG)                                           \
 (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))

My copy of the ANSI standard is a couple of years old.  It doesn't
make it entirely clear what behaviour is to be expected in a case
like this.  I see a reference to this change in the ChangeLog file
for Feb 1st 1988.  Although it is possible to pass the address of
the argument pointer, or to return the new value, it seems more
convenient to use the old method.


Dave Allen
Monotype International
Science Park
Milton Road
Cambridge
England