Bug 14557

Summary: va_list is automatically taken address-of when passed as argument
Product: gcc Reporter: Olof Lindholm <olof.lindholm>
Component: targetAssignee: Andreas Jaeger <aj>
Status: RESOLVED INVALID    
Severity: normal CC: gcc-bugs, gcc, ian-gccbug, jh, jkain, msebor
Priority: P2 Keywords: diagnostic, rejects-valid
Version: 3.3.3   
Target Milestone: ---   
Host: x86_64-suse-linux Target: x86_64-suse-linux
Build: Known to work:
Known to fail: Last reconfirmed:
Attachments: output of -show-temps
source file

Description Olof Lindholm 2004-03-12 16:17:19 UTC
Running x86_64, Suse 2.4.21-149-default.

Version:
 Configured with: ./configure 
 Thread model: posix
 gcc version 3.3.3

Command line:
 gcc -Wall -o apa apa.c

Output:
 apa.c: In function `bar':
 apa.c:17: warning: passing arg 2 of `baz' from incompatible pointer type

Source code:
 
#include <stdio.h>
#include <stdarg.h>

int
baz(int first, va_list *marker)
{
   int second = va_arg( *marker, int);
   va_end( *marker );
   return first+second;
}

int
bar(int first, va_list marker)
{
   return baz(first,&marker);
}

int
foo(int first, ...)
{
   va_list marker;
   va_start( marker, first );
   return bar(first, marker); 
}

int
main(int argc, char *argv[])
{
   printf( "returned %d\n", foo( 23, 11 ) );
   return 0;
}

Works if you change bar to:

int
bar(int first, va_list marker)
{
   return baz(first,marker);
}

Will attach .i and source file.
Comment 1 Olof Lindholm 2004-03-12 16:18:38 UTC
Created attachment 5908 [details]
output of -show-temps
Comment 2 Olof Lindholm 2004-03-12 16:19:21 UTC
Created attachment 5909 [details]
source file
Comment 3 Andrew Pinski 2004-03-12 16:27:52 UTC
Can you provide the output of "gcc -v" as it works for me on powerpc-apple-darwin7.2.0 and i686-pc-
linux-gnu?
Comment 4 Olof Lindholm 2004-03-12 16:32:48 UTC
gcc -v               
Reading specs from
/localhome/mygcc/bin/../lib/gcc-lib/x86_64-unknown-linux-gnu/3.3.3/specs
Configured with: ./configure 
Thread model: posix
gcc version 3.3.3

I have not seen to problem on any other platform than x86_64. Have tried
the specific microprogram on ia32-redhat-linux and it worked, but I 
only have an older version of gcc there (2.95.3)
Comment 5 Andrew Pinski 2004-03-12 17:04:20 UTC
Andreas said he would take care of it next week.
Comment 6 Josef Zlomek 2004-03-13 06:10:33 UTC
AFAIK it is incorrect to use "va_list *" so the code is wrong.
va_list is allowed to be something different that a pointer, for example
on ppc64 and x86-64 it is an one element array (builtin type).
Arrays are always passed as a pointer to the first element so there is no
performance penalty.
AFAIK using "&marker" where marker is va_list is wrong too.

See the discussion when we were fixing vasprintf.c from libiberty
http://gcc.gnu.org/ml/gcc-patches/2003-10/msg00219.html
Comment 7 falk.hueffner 2004-03-13 12:15:59 UTC
Subject: Re:  va_list is automatically taken address-of
 when passed as argument

"zlomek at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:

> ------- Additional Comments From zlomek at gcc dot gnu dot org  2004-03-13 06:10 -------
> AFAIK it is incorrect to use "va_list *" so the code is wrong.

I don't see anything wrong with using "va_list *". The standard even says:

     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.

About passing by value it says:

     The object ap 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.

Well, it doesn't invoke va_arg, so that should be fine, too.

Comment 8 Jan Hubicka 2004-03-13 13:13:09 UTC
Subject: Re:  va_list is automatically taken address-of when passed as argument

> 
> ------- Additional Comments From falk dot hueffner at student dot uni-tuebingen dot de  2004-03-13 12:15 -------
> Subject: Re:  va_list is automatically taken address-of
>  when passed as argument
> 
> "zlomek at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:
> 
> > ------- Additional Comments From zlomek at gcc dot gnu dot org  2004-03-13 06:10 -------
> > AFAIK it is incorrect to use "va_list *" so the code is wrong.
> 
> I don't see anything wrong with using "va_list *". The standard even says:
> 
>      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.
> 
> About passing by value it says:

My recollection from last time we were discussing this is that text
above is an footnote that is not normative and in conflict with rest of
the standard, so it needs to be ignored. While I agree that this
behaviour is very unfortuante side effect of va-arg implementation,
there are some other ABIS around (PPC SysV) doing the same so the only
choice now is probably to avoid this construct.

Honza
> 
>      The object ap 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.
> 
> Well, it doesn't invoke va_arg, so that should be fine, too.
> 
> 
> 
> -- 
> 
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557
> 
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug, or are watching someone who is.
Comment 9 hueffner 2004-03-13 13:20:23 UTC
Subject: Re:  va_list is automatically taken address-of
 when passed as argument

"jh at suse dot cz" <gcc-bugzilla@gcc.gnu.org> writes:

> My recollection from last time we were discussing this is that text
> above is an footnote that is not normative and in conflict with rest of
> the standard, so it needs to be ignored.

Okay, let's say we ignore it. Which part of the standard is violated
then?

Comment 10 Joseph S. Myers 2004-03-13 13:22:31 UTC
Subject: Re:  va_list is automatically taken address-of
 when passed as argument

On Sat, 13 Mar 2004, falk dot hueffner at student dot uni-tuebingen dot de wrote:

> I don't see anything wrong with using "va_list *". The standard even says:

There's nothing wrong with using va_list *, the only problem is when 
taking the address of a parameter to do so.

With a variable

va_list ap;

you use &ap to take the address.

With a parameter (subject to array-to-pointer adjustment)

  va_list ap

you use &ap if va_list is not an array type, but ap if it is an array
type.

Comment 11 hueffner 2004-03-13 13:28:42 UTC
Subject: Re:  va_list is automatically taken address-of
 when passed as argument

"jsm at polyomino dot org dot uk" <gcc-bugzilla@gcc.gnu.org> writes:

> ------- Additional Comments From jsm at polyomino dot org dot uk  2004-03-13 13:22 -------
> There's nothing wrong with using va_list *, the only problem is when
> taking the address of a parameter to do so.
>
> With a variable
>
> va_list ap;
>
> you use &ap to take the address.
>
> With a parameter (subject to array-to-pointer adjustment)
>
>   va_list ap
>
> you use &ap if va_list is not an array type, but ap if it is an
> array type.

Ah, I see. Thanks.

Comment 12 Zack Weinberg 2004-03-13 19:50:06 UTC
Subject: Re:  va_list is automatically taken address-of
 when passed as argument


&ap should always work; taking the address of an array produces a
pointer to the array, which has a different type but the same value as
the pointer to the first element that you get if you don't take the
address.  You have to write *ap in the callee, is all.

As far as I can see the original example is strictly conforming and
the warning should not be issued.

zw
Comment 13 Joseph S. Myers 2004-03-13 20:04:58 UTC
Subject: Re:  va_list is automatically taken address-of
 when passed as argument

On Sat, 13 Mar 2004, zack at codesourcery dot com wrote:

> &ap should always work; taking the address of an array produces a
> pointer to the array, which has a different type but the same value as
> the pointer to the first element that you get if you don't take the
> address.  You have to write *ap in the callee, is all.

The trouble is that in this example you're taking the address of a pointer
to the first element of the array (namely, the parameter declared with the
array type va_list which has pointer type because of the adjustment of
parameter types).

Comment 14 Zack Weinberg 2004-03-13 21:55:47 UTC
Subject: Re:  va_list is automatically taken address-of
 when passed as argument

"jsm at polyomino dot org dot uk" <gcc-bugzilla@gcc.gnu.org> writes:
> The trouble is that in this example you're taking the address of a
> pointer to the first element of the array (namely, the parameter
> declared with the array type va_list which has pointer type because
> of the adjustment of parameter types).

Ah, so what's unportable is taking the address of a va_list which has
been passed to you as a value parameter?  This I can see.

zw
Comment 15 Andrew Pinski 2005-04-11 17:07:12 UTC
*** Bug 20951 has been marked as a duplicate of this bug. ***
Comment 16 Andrew Pinski 2005-12-07 17:12:42 UTC
*** Bug 8262 has been marked as a duplicate of this bug. ***
Comment 17 Andrew Pinski 2006-02-15 03:26:14 UTC
*** Bug 26294 has been marked as a duplicate of this bug. ***
Comment 18 Andrew Pinski 2006-05-10 15:46:50 UTC
*** Bug 27534 has been marked as a duplicate of this bug. ***
Comment 19 felix 2017-09-10 11:26:06 UTC
The number of duplicates of this report isn't terribly high, but doesn't this at least deserve a mention in the 'Disappointments' section of the manual?

In any case, the following macro could be used as a workaround, under some rather reasonable assumptions:

#if __STDC_VERSION__ >= 201112L
#define va_ptr(ap) _Generic(&(ap), va_list *: &(ap), default: (va_list *)(ap))
#elif __GNUC__ >= 4
#define va_ptr(ap) __builtin_choose_expr(__builtin_types_compatible_p(__typeof__(&(ap)), va_list *), &(ap), (va_list *)(ap))
#else
#define va_ptr(ap) (sizeof(ap) == sizeof(va_list) ? (va_list *)&(ap) : (va_list *)(ap))
#endif

The main assumption is that a pointer to an array is the same as a pointer to its zeroth element, i.e. when we have a variable T array[N]; then (&array == (T (*)[N])array); or at least that this holds for the array type that va_list is. I don't see anything in the C standard that would explicitly guarantee this, but this should be a safe assumption to make, because breaking it would presumably make the following memcpy calls non-equivalent:

T array0[N], array1[N];

memcpy(array1, array0, sizeof(array0));
memcpy(&array1, array0, sizeof(array0));
memcpy(array1, &array0, sizeof(array0));
memcpy(&array1, &array0, sizeof(array0));

which would be strange. Furthermore, the last version will break in the presence of va_list defined like

typedef void *va_list[1];
typedef char va_list[sizeof(char *)];

but I think it's reasonable to assume that no ABI standard is going to prescribe something like this. None of the targets currently supported by GCC do.
Comment 20 nsz 2018-01-25 11:40:56 UTC
(In reply to felix from comment #19)
> The number of duplicates of this report isn't terribly high, but doesn't
> this at least deserve a mention in the 'Disappointments' section of the
> manual?
> 
> In any case, the following macro could be used as a workaround, under some
> rather reasonable assumptions:
> 
> #if __STDC_VERSION__ >= 201112L
> #define va_ptr(ap) _Generic(&(ap), va_list *: &(ap), default: (va_list
> *)(ap))
...

the standard conform way to deal with this issue is to

va_list ap2;
va_copy(ap2, ap);

and then use &ap2, this always works.

the proposed macros are both broken and unnecessary.
Comment 21 felix 2018-11-01 21:37:52 UTC
> va_list ap2;
> va_copy(ap2, ap);

> and then use &ap2, this always works.

> the proposed macros are both broken and unnecessary.

That's not equivalent. Using va_arg(ap2, T) does not propagate state changes back to ap, which is the main motivation to form a pointer to ap in the first place. The macros do that just fine. You mean they are unportable? That part is true, I admitted as much. Pick your poison.

As for being unnecessary, I vaguely remember gnulib trying to use internal helper functions with va_list * parameter in their vfprintf implementation. I cannot find the link now, unfortunately. But there are also duplicates to this very report, so clearly the need is there.
Comment 22 postmaster 2018-11-01 21:45:44 UTC
   Your email was bounced...
   -------------------------

   ... because something went wrong between you and your recipient. Oh
   no!


   What to do next?
   ----------------

   Well, your specific problem was a *5.1.2 * error.

   Which means you should: Check the "flash-gordon.me.uk" part of
   "gcc@flash-gordon.me.uk" for misspellings or missing letters. If you
   find an error, correct it in your contacts list or address book for
   next time.

   Or further: It is possible that the domain is temporarily inactive. If
   the spelling looks correct, contact your mail provider and if
   necessary, contact your recipient another way (e.g., phone or text
   message).

   Get more help on 5.1.2 errors here![1]

   Thanks, have a lovely day.

   Yours truly, betterbounces.net[2]

   Rate this email: Helpful[3] :) or... Not Helpful[4] :(

   Advertisement | Prefer no ads?[5]

   Learn more about RevenueStripe... [6]

   [7]

   ---------------------------------------------------------------------

   © 2017 betterbounces.net, All rights reserved. Privacy[8]

   [IMAGE] [IMAGE] [IMAGE] [IMAGE] [IMAGE]

   1. https://a.b-io.me/c/Y1lM9w9S1Kcyhmff9PUym3lzb4DFXoKjbQxPz_NW_WrQaWlkIsfqBNRgrwhzFkMcrwIXvcetvsZyskw3ba6cO13ry35GacumgC9FOm4QkNXaAORBfGNI9XaxlUM1jCpXwWSsHd4hBnlo3Ep2ClCJZR4F_2_Z944RQ_Ff1Hlr7qC5AubVwp4npLVx_SJUN89AI6R8sJU6BcnDevdyvtmr3XLv1zMnoJcUo9jOL4SdRznpTxVFk4gP6m8fUQOpJB.mCOXnPq7M.5.wEjbngsCiw9exDqQLI9eWwPLzORZhDw9W5V3M6SSy9ACeUE20ncsQuzenNfjXo4dd68t_RmnLpoAvRTpuEJDV4Lmq8o6zs9Abcgz_kivUcOhyaVuawoG6M11eQELWLpH0Vs8NmgE3MY0TiDO3KU_V7w0eHjri9.twOAjjam3qwa1jLaAvk31Y5x2e.65D9k7fK9V0PT4wI5Vx5wMoLgN7BUrvnfnF3YZJzSk9BM9xI3Ke3BiT6f4z
   2. https://a.b-io.me/c/Y1lM9w9S1Kcyhmff9PUym3lzb4DFXoKjbQxPz_NW_WrQaWlkIsfqBNRgrwhzFkMcrwIXvcetvsZyskw3ba6cO13ry35GacumgC9FOm4QkNXaAORBfGNI9XaxlUM1jCpXwWSsHd4hBnlo3Ep2ClCJZR4F_2_Z944RQ_Ff1Hlr7qC5AubVwp4npLVx_SJUN89AI6R8sJU6BcnOFzLscYDd_muBr0cqfVNXlAl73cWA7IEKNcxgbpC49DF.K_iHE4RwTSVvdmLIBNY7YexqWgPQgytJT9.x.rSqRNsT01JDgKk5i3vc0Jo.GX7ip_SABKQbP2D9EwQZROeSf8LgvA6Bm6.smm7wWn96mtx_vbla9ds-
   3. https://a.b-io.me/c/Y1lM9w9S1Kcyhmff9PUym3lzb4DFXoKjbQxPz_NW_WrQaWlkIsfqBNRgrwhzFkMcrwIXvcetvsZyskw3ba6cO13ry35GacumgC9FOm4QkNXaAORBfGNI9XaxlUM1jCpXwWSsHd4hBnlo3Ep2ClCJZR4F_2_Z944RQ_Ff1Hlr7qC5AubVwp4npLVx_SJUN89AI6R8sJU6BcnDevdyvtmr3SQCfDh9Nllm1xxkirU9iGeJRMIJCeh4_rhv8rSXZms8yV1cHIIO.DQHsbSiSXFFFwiIXVDY97IzEM2xKAcTY43fK9V0PT4wI5Vx5wMoLgN7BUrvnfnF3YZJzSk9BM9xIw1m1d7bBy4hf1IHxzL2mRzWLv9AFWPezwk_1D5f8BNpdyC560RQkF51r0i2tp95k0dMw9RD4ed6GYKls.oEbv9uyjjLmKbT9Z.wWV1osAHxEegkm0owPMW9YCxKQu84jWuwZdR7HRXoK76JsqyBH4bNNv1dlOjg3cVUlP4jpqDVLkHb3Deos.A-
   4. https://a.b-io.me/c/Y1lM9w9S1Kcyhmff9PUym3lzb4DFXoKjbQxPz_NW_WrQaWlkIsfqBNRgrwhzFkMcrwIXvcetvsZyskw3ba6cO13ry35GacumgC9FOm4QkNXaAORBfGNI9XaxlUM1jCpXwWSsHd4hBnlo3Ep2ClCJZR4F_2_Z944RQ_Ff1Hlr7qC5AubVwp4npLVx_SJUN89AI6R8sJU6BcnDevdyvtmr3SQCfDh9Nllm1xxkirU9iGeJRMIJCeh4_rhv8rSXZms8yV1cHIIO.DQHsbSiSXFFFwiIXVDY97IzEM2xKAcTY43fK9V0PT4wI5Vx5wMoLgN7BUrvnfnF3YZJzSk9BM9xIw1m1d7bBy4hb3qihMYau.6R3JspOZZpeDDWIM2ZwsZ7twKFN2dpifDGPOdSRj1EW1sVg4IarW8oQgLry3CN1jdwmv86NTcKo2UsMKSQNmn82g9GaB.Aab_hFWGduKelhd_zkhoBta3xbetkl8tJBjdEecbdRMWk0eR.hPW394lfunbII79SX7y0zhgaUCFBhw--
   5. https://a.b-io.me/c/Y1lM9w9S1Kcyhmff9PUym3lzb4DFXoKjbQxPz_NW_WrQaWlkIsfqBNRgrwhzFkMcrwIXvcetvsZyskw3ba6cO13ry35GacumgC9FOm4QkNXaAORBfGNI9XaxlUM1jCpXwWSsHd4hBnlo3Ep2ClCJZR4F_2_Z944RQ_Ff1Hlr7qC5AubVwp4npLVx_SJUN89AI6R8sJU6BcnDevdyvtmr3XQSZ5q7Uj4AUiZ.VwRVR0uATpJf4wwi2VBn2uyg_TniJvFx9Ykk4tGemAGZEpURvQmxJqhFX9kmefyRbN3anZT9Psy7Qwp1WuVTAYoDkjUpMkJpEhGzSVxLxWi8A5ZosYQm_CP1pW5QZqRpWSOTdGnJOZ61Se8VxvmwfXh4AY9ZrCMU63YPBX6ZA78PdxvP7lEgrAZUzHfGczjz_39.lBKQyr_yKuIpcw0m7EMQCkaZbNaX8qEZceMGLyBYMb6g.rs7WCkhrE5ikz5PafL2GJQOU1vvVOy7NrL198gM8C_0GyRdSM2zDileyARIlxoX8ALjoCwa9JXkiP05sPdmZlwzQLq1fShUUsp9g0aXOz_70iG9nz4Wv68V5vR7aSs.xbCQtqhEsq8Opq2EUc4yTtsKuku9TC1tIkVG7Z9qPDn.MIqQ0vOJX8C6YenpnQz7iAvXX62x1Bw1m.SoyXmrjN4QkYwd_7HhsLcChTdnaYnwxjznUkY9RFtbFYOCGq1vKEIC68twjdY3cJr.OjU3CqNCmkqgAAsbqycQQoH55CiX_9YQ48RbRVB7f19k7IEXcOg3DCBOR.7WCtl3OoIThpaH6PFz4jRZ4A--
   6. https://a.b-io.me/c/Y1lM9w9S1Kcyhmff9PUym3lzb4DFXoKjbQxPz_NW_WrQaWlkIsfqBNRgrwhzFkMcrwIXvcetvsZyskw3ba6cO13ry35GacumgC9FOm4QkNXaAORBfGNI9XaxlUM1jCpXwWSsHd4hBnlo3Ep2ClCJZR4F_2_Z944RQ_Ff1Hlr7qC5AubVwp4npLVx_SJUN89AI6R8sJU6BcnOFzLscYDd_vqRDj0SoJx6X2cUYMUBoBnyYh259jgZLmu.gJrc5PREAHsseYstd5eqVluqQ1VKEsgcWQVaFzMA41D4N7g_a.VK0zKni9IiUiMz1vh9HNUt1H5z5sniDd6InEr4aMXaSQmRFYCWbTvSR_ac7UAeZLRbmJtFzgH07TcucLjIcQBxz0iGtaebo9OPe_CcwUVyeIDpoLkMXVoov_BsjwMPeOW2qB12AEKQkr1gLEpC7ziNa7Bl1HsdFegrvomyrIEfhs02.V2U6ODdxVSU.iOmoNUuQdvcN6iz8A--
   7. https://a.b-io.me/c/Y1lM9w9S1Kcyhmff9PUym3lzb4DFXoKjbQxPz_NW_WrQaWlkIsfqBNRgrwhzFkMcrwIXvcetvsZyskw3ba6cO13ry35GacumgC9FOm4QkNXaAORBfGNI9XaxlUM1jCpXwWSsHd4hBnlo3Ep2ClCJZR4F_2_Z944RQ_Ff1Hlr7qC5AubVwp4npLVx_SJUN89AI6R8sJU6BcnOFzLscYDd_nvhsHDpeErFT9ujPR.S.S.OTuCQ1AcE58yCnaaGRjo0AFRhpX6WYHsgxI2PLfTUqvyoHTevVH4KjWhfxulCynmhq13SFHUO0jB2muQSPg_3SJ0IQqs0_Ueh5G7FUEOOOEKdML5h84VlSYbjsz_N1HGHQOs5n.1E7s1DI3iSpGDB_N3yMYqvuBcr6XwBibKM4P3LdsZfK.Q2M11eQELWLpH0Vs8NmgE3MY0TiDO3KU_V7w0eHjri9.twOAjjam3qwa1jLaAvk31Y5x2e.65D9k7fK9V0PT4wI5Vx5wMoLgN7BUrvnfnF3YZJzSk9BM9xI3Ke3BiT6f4z
   8. https://a.b-io.me/c/Y1lM9w9S1Kcyhmff9PUym3lzb4DFXoKjbQxPz_NW_WrQaWlkIsfqBNRgrwhzFkMcrwIXvcetvsZyskw3ba6cO13ry35GacumgC9FOm4QkNXaAORBfGNI9XaxlUM1jCpXwWSsHd4hBnlo3Ep2ClCJZR4F_2_Z944RQ_Ff1Hlr7qC5AubVwp4npLVx_SJUN89AI6R8sJU6BcnDevdyvtmr3XLv1zMnoJcUo9jOL4SdRzmgYGya.Yip6kk9.QLUBM15GQzYjJN.vEkzXV5AQtYukfRWzw2aATcxjROIM7cpT5XvDR4eOuL3_3A4CONqberBrWMtoC_TfVjnHZ7.rkP2Tt8r1XQ9PjAjlXHnAyguA3sFSu_d_cXdhknNKT0Ez3Ejcp7cGJPp.jM-
Comment 23 nsz 2018-11-02 11:29:10 UTC
(In reply to felix from comment #21)
> > va_list ap2;
> > va_copy(ap2, ap);
> 
> > and then use &ap2, this always works.
> 
> > the proposed macros are both broken and unnecessary.
> 
> That's not equivalent. Using va_arg(ap2, T) does not propagate state changes
> back to ap, which is the main motivation to form a pointer to ap in the
> first place. The macros do that just fine. You mean they are unportable?
> That part is true, I admitted as much. Pick your poison.
> 

state changes are propagated to ap2, which is
what you should use after you made the copy,
it does exactly what you want.