public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "joseph at codesourcery dot com" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug c/50581] stdarg doesn't support array types
Date: Sat, 01 Oct 2011 14:08:00 -0000	[thread overview]
Message-ID: <bug-50581-4-TnGuBIFB0r@http.gcc.gnu.org/bugzilla/> (raw)
In-Reply-To: <bug-50581-4@http.gcc.gnu.org/bugzilla/>

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

--- Comment #3 from joseph at codesourcery dot com <joseph at codesourcery dot com> 2011-10-01 14:07:42 UTC ---
On Sat, 1 Oct 2011, Wolfgang at Solfrank dot net wrote:

> > 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

That the C semantics mean that:

* for C90 it is impossible to access values in the non-lvalue array passed 
(the existence of the possibility of passing an array by value to a 
variadic function in C90 is one of the most obscure and useless C 
standards corner cases there is);

* for C99, calling va_arg with such a type always results in undefined 
behavior at runtime because a pointer will have been passed rather than an 
array.

So no valid C program can ever actually access a value in this way.  Of 
course, if you tried to pass an *lvalue* array (the normal case for arrays 
in C) then it was converted to a pointer rather than passed by value, for 
both C90 and C99, and so you had undefined behavior at runtime, for both 
C90 and C99.

If you want to access a pointer, you need to pass a pointer type to 
va_arg.  This is just like accessing a promoted float or char where you 
need to specify "double" or "int".  Which is why generating an abort with 
a warning at compile time seems appropriate - it's the well-established 
practice for "char" and "float" here.  (Given the obscurity, there should 
probably be a warning for C90 as well, but without the abort.)

> > 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.

Here is an example program that is valid as C90 but not as C99.  It passes 
for me with all the C90 options I tried.  That is, the caller and callee 
are consistent about the space expected to be taken by the array on the 
stack, which is all that's required since there is no way of accessing the 
array's value.  (C ABIs won't generally specify this for interoperation 
between implementations, given that passing by value an array whose value 
you can't access isn't useful and the possibility of doing so has 
disappeared in C99.)

#include <stdarg.h>

extern void abort (void);
extern void exit (int);

typedef char array[10000];
struct s { array a; } x;
void g (int a, ...);

int
main (void)
{
  g (0, (0, x).a, 1234);
  exit (0);
}

void
g (int a, ...)
{
  va_list ap;
  va_start (ap, a);
  va_arg (ap, array);
  if (va_arg (ap, int) != 1234)
    abort ();
  va_end (ap);
}

> 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

Passing va_list as a function argument is generally hard, whether or not 
variadic, since you don't know whether it will be passed by reference or 
by value or what the type of the address of a va_list parameter will be.  
Portable code needs to pass a pointer to va_list or a structure containing 
va_list or use some other such means of avoiding dependence on whether 
va_list is an array.


  parent reply	other threads:[~2011-10-01 14:08 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-09-30 15:49 [Bug c/50581] New: " Wolfgang at Solfrank dot net
2011-09-30 20:13 ` [Bug c/50581] " joseph at codesourcery dot com
2011-10-01 11:07 ` Wolfgang at Solfrank dot net
2011-10-01 14:08 ` joseph at codesourcery dot com [this message]
2011-10-01 14:43 ` Wolfgang at Solfrank dot net
2011-10-01 18:46 ` joseph at codesourcery dot com
2011-10-02 16:09 ` Wolfgang at Solfrank dot net
2011-10-02 19:48 ` svfuerst at gmail dot com
2022-01-03  2:38 ` pinskia at gcc dot gnu.org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-50581-4-TnGuBIFB0r@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).