public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Different behaviour of stdarg as function of platform, is this a bug?
@ 2000-06-07 14:34 Carlo Wood
  2000-06-07 14:46 ` Franz Sirl
  2000-06-07 15:08 ` Zack Weinberg
  0 siblings, 2 replies; 6+ messages in thread
From: Carlo Wood @ 2000-06-07 14:34 UTC (permalink / raw)
  To: gcc; +Cc: carlo

The gcc implementation of stdarg is such that the behaviour
is different on different platforms.

I am wondering what is the correct ANSI behaviour, and if
gcc is conforming to this behaviour for all platforms or
that this is a bug.

Consider the little test program below; on most operating systems
the result is what I get (among others) on ix86/linux:

~/c/tests>uname -a
Linux jolan 2.3.99-pre9 #4 Tue May 16 16:10:46 CEST 2000 i686 unknown

~/c/tests>a.out
vfoo: 1 2
vfoo: 1 2

However, on ppc/linux (on a Mac - so far the only platform for which this
was reported to me) the result is:

$ uname -a
Linux www2.mhs.k12.oh.us 2.2.15pre3 #3 Sat Jan 29 18:02:45 CET 2000 ppc unknown

$ a.out
vfoo: 1 2
vfoo: 3 4

The reason for this difference is the difference in
/usr/lib/gcc-lib/ppc-redhat-linux/2.95.2/include/va-ppc.h compared to
the implementation used for ix86: on the ppc a "pointer" type is passed
to `vfoo' for the va_list, while on the ix86 it passes the va_list by value.
The former case causes `vl' to be changed after the first return from
vfoo() in the loop (now pointing to the third argument instead of the first).

Please keep the CC to me, as I am not subbed to this list.

-- 
Carlo Wood <carlo@alinoe.com>                           -=- Jesus Loves you -=-

The test program:

----------------------------------snip------------------------------------
#include <stdio.h>
#include <stdarg.h>

void vfoo(va_list vl)
{
  int a, b;
  a = va_arg(vl, int);
  b = va_arg(vl, int);
  printf("vfoo: %d %d\n", a, b);
}

void foo(int x, ...)
{
  int i;
  va_list vl;
  va_start(vl, x);
  for (i = 0; i < 2; ++i)
    vfoo(vl);
  va_end(vl);
}

int main(void)
{
  int a = 1, b = 2, c = 3, d = 4;
  foo(0, a, b, c, d);
  return 0;
}

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Different behaviour of stdarg as function of platform, is this a bug?
  2000-06-07 14:34 Different behaviour of stdarg as function of platform, is this a bug? Carlo Wood
@ 2000-06-07 14:46 ` Franz Sirl
  2000-06-07 15:08 ` Zack Weinberg
  1 sibling, 0 replies; 6+ messages in thread
From: Franz Sirl @ 2000-06-07 14:46 UTC (permalink / raw)
  To: Carlo Wood, gcc; +Cc: carlo

On Wed, 07 Jun 2000, Carlo Wood wrote:
> The gcc implementation of stdarg is such that the behaviour
> is different on different platforms.
>
> I am wondering what is the correct ANSI behaviour, and if
> gcc is conforming to this behaviour for all platforms or
> that this is a bug.
>
> Consider the little test program below; on most operating systems
> the result is what I get (among others) on ix86/linux:
>
> ~/c/tests>uname -a
> Linux jolan 2.3.99-pre9 #4 Tue May 16 16:10:46 CEST 2000 i686 unknown
>
> ~/c/tests>a.out
> vfoo: 1 2
> vfoo: 1 2
>
> However, on ppc/linux (on a Mac - so far the only platform for which this
> was reported to me) the result is:
>
> $ uname -a
> Linux www2.mhs.k12.oh.us 2.2.15pre3 #3 Sat Jan 29 18:02:45 CET 2000 ppc
> unknown
>
> $ a.out
> vfoo: 1 2
> vfoo: 3 4
>
> The reason for this difference is the difference in
> /usr/lib/gcc-lib/ppc-redhat-linux/2.95.2/include/va-ppc.h compared to
> the implementation used for ix86: on the ppc a "pointer" type is passed
> to `vfoo' for the va_list, while on the ix86 it passes the va_list by
> value. The former case causes `vl' to be changed after the first return
> from vfoo() in the loop (now pointing to the third argument instead of the
> first).
>
> Please keep the CC to me, as I am not subbed 
to this list.

Your code is wrong, it should read:

void foo(int x, ...)
{
  int i;
  va_list vl;
  for (i = 0; i < 2; ++i)
  {
      va_start(vl, x);
      vfoo(vl);
      va_end(vl);
  }
}                                                                             

You are relying on implementation details otherwise.

Franz.
                                                                     

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Different behaviour of stdarg as function of platform, is this a bug?
  2000-06-07 14:34 Different behaviour of stdarg as function of platform, is this a bug? Carlo Wood
  2000-06-07 14:46 ` Franz Sirl
@ 2000-06-07 15:08 ` Zack Weinberg
  2000-06-07 15:29   ` Franz Sirl
  1 sibling, 1 reply; 6+ messages in thread
From: Zack Weinberg @ 2000-06-07 15:08 UTC (permalink / raw)
  To: Carlo Wood; +Cc: gcc

On Wed, Jun 07, 2000 at 11:34:03PM +0200, Carlo Wood wrote:
> The gcc implementation of stdarg is such that the behaviour
> is different on different platforms.
> 
> I am wondering what is the correct ANSI behaviour, and if
> gcc is conforming to this behaviour for all platforms or
> that this is a bug.

Your program does something which is not permitted by the C standard.
Section 7.15 paragraph 3 of C99 reads in part

	[An object] ap [of type va_list] may be passed as an argument
	to another function; if that function invokes the va_arg macro
	with parameter ap, the value of ap in the calling function is
	indeterminate and shall be passed to the va_end macro prior to
	any further reference to ap.(212)

	212) It is permitted to create a pointer to a va_list and pass
	that pointer to another function, in which case the original
	function may make further use of the original list after the
	other function returns.

This section is quite badly written - not unusual for the C standard,
alas.  Anyway, what they mean is that the only thing you can legally
do with vl after vfoo() returns is destroy it and recreate it.  If you
had written

void foo(int x, ...)
{
  int i;
  va_list vl;
  for(i = 0; i < 2; ++i)
  {
    va_start(vl, x);
    vfoo(vl);
    va_end(vl);
  }
}

your program would be well-defined.  C99 provides va_copy() which
could also be used in this context.

I think the footnote means you could get the ppc/linux behavior
reliably by writing

void vfoo(va_list *vl)
{
  int a, b;
  a = va_arg(*vl, int);
  b = va_arg(*vl, int);
  printf("vfoo: %d %d\n", a, b);
}
 
void foo(int x, ...)
{
  int i;
  va_list vl;
  va_start(vl, x);
  for (i = 0; i < 2; ++i)
    vfoo(&vl);
  va_end(vl);
}

but I would not do this in code intended to be portable.

zw

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Different behaviour of stdarg as function of platform, is this a bug?
  2000-06-07 15:08 ` Zack Weinberg
@ 2000-06-07 15:29   ` Franz Sirl
  2000-06-07 15:46     ` Zack Weinberg
  0 siblings, 1 reply; 6+ messages in thread
From: Franz Sirl @ 2000-06-07 15:29 UTC (permalink / raw)
  To: Zack Weinberg, Carlo Wood; +Cc: gcc

On Thu, 08 Jun 2000, Zack Weinberg wrote:
> I think the footnote means you could get the ppc/linux behavior
> reliably by writing
>
> void vfoo(va_list *vl)
> {
>   int a, b;
>   a = va_arg(*vl, int);
>   b = va_arg(*vl, int);
>   printf("vfoo: %d %d\n", a, b);
> }
>
> void foo(int x, ...)
> {
>   int i;
>   va_list vl;
>   va_start(vl, x);
>   for (i = 0; i < 2; ++i)
>     vfoo(&vl);
>   va_end(vl);
> }
>
> but I would not do this in code intended to be portable.

No, this doesn't change anything :-), va_list is an array in PPC-SYSV ABI, so 
it will always be passed as a pointer.

Franz.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Different behaviour of stdarg as function of platform, is this a bug?
  2000-06-07 15:29   ` Franz Sirl
@ 2000-06-07 15:46     ` Zack Weinberg
  2000-06-07 15:53       ` Franz Sirl
  0 siblings, 1 reply; 6+ messages in thread
From: Zack Weinberg @ 2000-06-07 15:46 UTC (permalink / raw)
  To: Franz Sirl; +Cc: Carlo Wood, gcc

On Thu, Jun 08, 2000 at 12:29:21AM +0200, Franz Sirl wrote:
> On Thu, 08 Jun 2000, Zack Weinberg wrote:
> > I think the footnote means you could get the ppc/linux behavior
> > reliably by writing
> >
> > void vfoo(va_list *vl)
> > {
> >   int a, b;
> >   a = va_arg(*vl, int);
> >   b = va_arg(*vl, int);
> >   printf("vfoo: %d %d\n", a, b);
> > }
> >
> > void foo(int x, ...)
> > {
> >   int i;
> >   va_list vl;
> >   va_start(vl, x);
> >   for (i = 0; i < 2; ++i)
> >     vfoo(&vl);
> >   va_end(vl);
> > }
> >
> > but I would not do this in code intended to be portable.
> 
> No, this doesn't change anything :-), va_list is an array in PPC-SYSV ABI, so 
> it will always be passed as a pointer.

Yes, but on other platforms it is passed by value.  On those
platforms, this should get you the same behavior as you get by default
on PPC.

zw

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Different behaviour of stdarg as function of platform, is this a bug?
  2000-06-07 15:46     ` Zack Weinberg
@ 2000-06-07 15:53       ` Franz Sirl
  0 siblings, 0 replies; 6+ messages in thread
From: Franz Sirl @ 2000-06-07 15:53 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Carlo Wood, gcc

On Thu, 08 Jun 2000, Zack Weinberg wrote:
> On Thu, Jun 08, 2000 at 12:29:21AM +0200, Franz Sirl wrote:
> > On Thu, 08 Jun 2000, Zack Weinberg wrote:
> > > I think the footnote means you could get the ppc/linux behavior
> > > reliably by writing
> > >
> > > void vfoo(va_list *vl)
> > > {
> > >   int a, b;
> > >   a = va_arg(*vl, int);
> > >   b = va_arg(*vl, int);
> > >   printf("vfoo: %d %d\n", a, b);
> > > }
> > >
> > > void foo(int x, ...)
> > > {
> > >   int i;
> > >   va_list vl;
> > >   va_start(vl, x);
> > >   for (i = 0; i < 2; ++i)
> > >     vfoo(&vl);
> > >   va_end(vl);
> > > }
> > >
> > > but I would not do this in code intended to be portable.
> >
> > No, this doesn't change anything :-), va_list is an array in PPC-SYSV
> > ABI, so it will always be passed as a pointer.
>
> Yes, but on other platforms it is passed by value.  On those
> platforms, this should get you the same behavior as you get by default
> on PPC.

Argh, I misread your initial statement. Yes, you are right.

Franz.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2000-06-07 15:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-06-07 14:34 Different behaviour of stdarg as function of platform, is this a bug? Carlo Wood
2000-06-07 14:46 ` Franz Sirl
2000-06-07 15:08 ` Zack Weinberg
2000-06-07 15:29   ` Franz Sirl
2000-06-07 15:46     ` Zack Weinberg
2000-06-07 15:53       ` Franz Sirl

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