http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50581

--- Comment #2 from Wolfgang at Solfrank dot net 2011-10-01 11:06:48 UTC ---
(In reply to comment #1)

Sorry, I don't quite follow you:

> There is no possible valid use of passing arrays to va_arg.

What makes you think so?  While the 1003.1 definition of va_arg explicitly
specifies that the behaviour when passing a type to va_arg that "is not
compatible with the type of the actual next argument (as promoted according to
the default argument promotions)" is undefined, that doesn't preclude to
implement something reasonable, does it?

> In C90, it is technically possible to use va_arg in this case without 
> undefined behavior.  The argument passed to the function would have to be 
> a non-lvalue array - for example, an array in a structure returned from 
> another function.  The result of va_arg would itself be a non-lvalue 
> array, which it is not possible to convert to a pointer, so it is not 
> possible to access the values in the array in any way; all that can be 
> done is to discard the value (call va_arg for its side effects) or to pass 
> it to another variadic function.

Well, I'm not sure that I buy that.  But even then, the current implementation
in gcc doesn't generate the correct code even only for the side effects.  The
generated code in fact assumes that the array is passed by value, i.e. the
pointer into the argument list (or something equivalent) is incremented by the
size of the array instead of the size of a pointer.

My main use case for this feature isn't with random arrays, but with va_list
itself.  On some architectures (AFAIK all architectures that pass some
arguments in registers) gcc implements va_list as a one element array of some
structure.  Without my proposed change, it isn't possible to have a va_list as
an argument to a variadic function.  This is what my second example in the bug
report was about.  To show it in a somewhat more real live example, let's
assume that vprintf implemented such a feature, something like (using %^ to
mean the next two arguments are a format string and a va_list):
-------------------------------------------
#include <stdarg.h>

int
vprintf(char *fmt, va_list ap)
{
        char *fmt1;
        va_list ap1;

        while (*fmt)
                if (*fmt == '%')
                        switch (*++fmt) {
                        case '^':
                                fmt1 = va_arg(ap, char *);
                                va_copy(ap1, va_arg(ap, va_list));
                                vprintf(fmt1, ap1);
                                va_end(ap1);
                                break;
....
                        }
...
}
-------------------------------------------
With current gcc, code like this works as expected on processors that implement
va_list as a pointer into the parameter list passed on the stack, but doesn't
work for processors passing arguments in registers therefor implement va_list
as thje above mentioned one element array.

Even if I buy your arguments, I consider it a bug that while with -std=c89 the
compiler spits an error message, but with -std=c99 it silently generates
incorrect code.

Reply via email to