Message ID | CAN8C2CpXVH8iq=9XMV0JxWPJihRi_vHDwHwMC830=YCxV-ZjNQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
Series | nano printf + powerpc gcc | expand |
On Dec 25 16:39, Alexander Fedotov wrote: > Hi > > I'm experienced a strange printf() for float variables behaviour with > Nano version while regular is fine. It just prins out a garbage (even > with enabled -u _printf_float). After some digging I've managed to > track down issue until this line: > > n = _printf_float (data, &prt_data, fp, pfunc, &ap); > > > Moreover there are number of warnings also in build log: > > src_newlib/newlib/libc/stdio/nano-vfprintf.c -o lib_a-nano-svfprintf.o > ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c: In > function '_svfprintf_r': > ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:645:55: > warning: passing argument 5 of '_printf_float' from incompatible > pointer type > n = _printf_float (data, &prt_data, fp, pfunc, &ap); > ^ > In file included from > ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: > ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:228:1: > note: expected 'struct __va_list_tag (*)[1]' but argument is of type > 'struct __va_list_tag **' > _printf_float (struct _reent *data, > ^ > ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:650:45: > warning: passing argument 5 of '_printf_i' from incompatible pointer > type > n = _printf_i (data, &prt_data, fp, pfunc, &ap); > ^ > In file included from > ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: > ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:221:1: > note: expected 'struct __va_list_tag (*)[1]' but argument is of type > 'struct __va_list_tag **' > _printf_i (struct _reent *data, struct _prt_data_t *pdata, FILE *fp, > > > It looks like nano written without taking in mind such targets. Here I > found workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 > that's working. > > I'm attaching a patch. > > Alex Pushed. Thanks, Corinna -- Corinna Vinschen Cygwin Maintainer Red Hat
Hi Alexander, This patch is causing our arm-none-eabi-gcc newlib-nano builds to fail. It seems the _Generic isn't picking up the right type when ap is of type va_list. We get the following error: newlib/libc/stdio/nano-vfscanf.c:430:2: error: cannot convert to a pointer type ret = _scanf_chars (rptr, &scan_data, fp, va_ptr(ap)); ^~~ newlib/libc/stdio/nano-vfscanf.c:432:2: error: cannot convert to a pointer type ret = _scanf_i (rptr, &scan_data, fp, va_ptr(ap)); ^~~ newlib/libc/stdio/nano-vfscanf.c:435:2: error: cannot convert to a pointer type ret = _scanf_float (rptr, &scan_data, fp, va_ptr(ap)); A reduced test-case, see: #include <stdio.h> extern void bar(va_list *ap); void foo(va_list ap) { bar(_Generic(&(ap), va_list *: &(ap), default: (va_list *)(ap))); } Note that va_list for our toolchain is defined as gcc's __builtin_va_list. I have tried your other definitions of va_ptr too and none of them seem to work. How do you suggest we proceed? Cheers, Andre On 08/01/18 10:07, Corinna Vinschen wrote: > On Dec 25 16:39, Alexander Fedotov wrote: >> Hi >> >> I'm experienced a strange printf() for float variables behaviour with >> Nano version while regular is fine. It just prins out a garbage (even >> with enabled -u _printf_float). After some digging I've managed to >> track down issue until this line: >> >> n = _printf_float (data, &prt_data, fp, pfunc, &ap); >> >> >> Moreover there are number of warnings also in build log: >> >> src_newlib/newlib/libc/stdio/nano-vfprintf.c -o lib_a-nano-svfprintf.o >> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c: In >> function '_svfprintf_r': >> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:645:55: >> warning: passing argument 5 of '_printf_float' from incompatible >> pointer type >> n = _printf_float (data, &prt_data, fp, pfunc, &ap); >> ^ >> In file included from >> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: >> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:228:1: >> note: expected 'struct __va_list_tag (*)[1]' but argument is of type >> 'struct __va_list_tag **' >> _printf_float (struct _reent *data, >> ^ >> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:650:45: >> warning: passing argument 5 of '_printf_i' from incompatible pointer >> type >> n = _printf_i (data, &prt_data, fp, pfunc, &ap); >> ^ >> In file included from >> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: >> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:221:1: >> note: expected 'struct __va_list_tag (*)[1]' but argument is of type >> 'struct __va_list_tag **' >> _printf_i (struct _reent *data, struct _prt_data_t *pdata, FILE *fp, >> >> >> It looks like nano written without taking in mind such targets. Here I >> found workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 >> that's working. >> >> I'm attaching a patch. >> >> Alex > > Pushed. > > > Thanks, > Corinna >
Hello Andre Yes indeed this fix unfortunately broke an ARM port. I have no idea why this builtins doesn't work on gcc for arm. Best way I believe right now is to revert this commit. Alex On Tue, Jan 23, 2018 at 5:04 PM, Andre Vieira (lists) <Andre.SimoesDiasVieira@arm.com> wrote: > Hi Alexander, > > This patch is causing our arm-none-eabi-gcc newlib-nano builds to fail. > > It seems the _Generic isn't picking up the right type when ap is of type > va_list. We get the following error: > newlib/libc/stdio/nano-vfscanf.c:430:2: error: cannot convert to a > pointer type > ret = _scanf_chars (rptr, &scan_data, fp, va_ptr(ap)); > ^~~ > newlib/libc/stdio/nano-vfscanf.c:432:2: error: cannot convert to a > pointer type > ret = _scanf_i (rptr, &scan_data, fp, va_ptr(ap)); > ^~~ > newlib/libc/stdio/nano-vfscanf.c:435:2: error: cannot convert to a > pointer type > ret = _scanf_float (rptr, &scan_data, fp, va_ptr(ap)); > > > A reduced test-case, see: > > #include <stdio.h> > extern void bar(va_list *ap); > void foo(va_list ap) { > bar(_Generic(&(ap), va_list *: &(ap), default: (va_list *)(ap))); > } > > Note that va_list for our toolchain is defined as gcc's __builtin_va_list. > > I have tried your other definitions of va_ptr too and none of them seem > to work. How do you suggest we proceed? > > Cheers, > Andre > > > > On 08/01/18 10:07, Corinna Vinschen wrote: >> On Dec 25 16:39, Alexander Fedotov wrote: >>> Hi >>> >>> I'm experienced a strange printf() for float variables behaviour with >>> Nano version while regular is fine. It just prins out a garbage (even >>> with enabled -u _printf_float). After some digging I've managed to >>> track down issue until this line: >>> >>> n = _printf_float (data, &prt_data, fp, pfunc, &ap); >>> >>> >>> Moreover there are number of warnings also in build log: >>> >>> src_newlib/newlib/libc/stdio/nano-vfprintf.c -o lib_a-nano-svfprintf.o >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c: In >>> function '_svfprintf_r': >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:645:55: >>> warning: passing argument 5 of '_printf_float' from incompatible >>> pointer type >>> n = _printf_float (data, &prt_data, fp, pfunc, &ap); >>> ^ >>> In file included from >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:228:1: >>> note: expected 'struct __va_list_tag (*)[1]' but argument is of type >>> 'struct __va_list_tag **' >>> _printf_float (struct _reent *data, >>> ^ >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:650:45: >>> warning: passing argument 5 of '_printf_i' from incompatible pointer >>> type >>> n = _printf_i (data, &prt_data, fp, pfunc, &ap); >>> ^ >>> In file included from >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:221:1: >>> note: expected 'struct __va_list_tag (*)[1]' but argument is of type >>> 'struct __va_list_tag **' >>> _printf_i (struct _reent *data, struct _prt_data_t *pdata, FILE *fp, >>> >>> >>> It looks like nano written without taking in mind such targets. Here I >>> found workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 >>> that's working. >>> >>> I'm attaching a patch. >>> >>> Alex >> >> Pushed. >> >> >> Thanks, >> Corinna >> > -- Best regards, AF
Hi, I looked a bit further into this and I can't reproduce this behavior for the i386 backend. So I had a look through GCC's parser implementation for _Generic and it seems GCC evaluates the expressions in each matching case, that is to say it will also parse the default case. In arm, the type of va_list is a struct, since it is invalid to cast structs to pointers, the c-parser will error out when it parses this cast in the default case. For an i386 gcc, and I'm guessing your case is the same, the type of va_list can be cast to a pointer type, so it parses it without errors. I don't know if parsing the expression of default if another case has matched is intended behavior. I will investigate this further and if I can convince myself this is wrong behavior I'll chase it with upstream gcc. On the other hand, I believe we can leave out the cast here, since the prototype for the function taking this as a parameter should be explicitly trying to cast it if that gets picked anyway no? I tried it with a pet example and it compiles if I leave out the cast for the 'default' case on all three implementations of va_ptr. Cheers, Andre On 23/01/18 14:04, Andre Vieira (lists) wrote: > Hi Alexander, > > This patch is causing our arm-none-eabi-gcc newlib-nano builds to fail. > > It seems the _Generic isn't picking up the right type when ap is of type > va_list. We get the following error: > newlib/libc/stdio/nano-vfscanf.c:430:2: error: cannot convert to a > pointer type > ret = _scanf_chars (rptr, &scan_data, fp, va_ptr(ap)); > ^~~ > newlib/libc/stdio/nano-vfscanf.c:432:2: error: cannot convert to a > pointer type > ret = _scanf_i (rptr, &scan_data, fp, va_ptr(ap)); > ^~~ > newlib/libc/stdio/nano-vfscanf.c:435:2: error: cannot convert to a > pointer type > ret = _scanf_float (rptr, &scan_data, fp, va_ptr(ap)); > > > A reduced test-case, see: > > #include <stdio.h> > extern void bar(va_list *ap); > void foo(va_list ap) { > bar(_Generic(&(ap), va_list *: &(ap), default: (va_list *)(ap))); > } > > Note that va_list for our toolchain is defined as gcc's __builtin_va_list. > > I have tried your other definitions of va_ptr too and none of them seem > to work. How do you suggest we proceed? > > Cheers, > Andre > > > > On 08/01/18 10:07, Corinna Vinschen wrote: >> On Dec 25 16:39, Alexander Fedotov wrote: >>> Hi >>> >>> I'm experienced a strange printf() for float variables behaviour with >>> Nano version while regular is fine. It just prins out a garbage (even >>> with enabled -u _printf_float). After some digging I've managed to >>> track down issue until this line: >>> >>> n = _printf_float (data, &prt_data, fp, pfunc, &ap); >>> >>> >>> Moreover there are number of warnings also in build log: >>> >>> src_newlib/newlib/libc/stdio/nano-vfprintf.c -o lib_a-nano-svfprintf.o >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c: In >>> function '_svfprintf_r': >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:645:55: >>> warning: passing argument 5 of '_printf_float' from incompatible >>> pointer type >>> n = _printf_float (data, &prt_data, fp, pfunc, &ap); >>> ^ >>> In file included from >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:228:1: >>> note: expected 'struct __va_list_tag (*)[1]' but argument is of type >>> 'struct __va_list_tag **' >>> _printf_float (struct _reent *data, >>> ^ >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:650:45: >>> warning: passing argument 5 of '_printf_i' from incompatible pointer >>> type >>> n = _printf_i (data, &prt_data, fp, pfunc, &ap); >>> ^ >>> In file included from >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: >>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:221:1: >>> note: expected 'struct __va_list_tag (*)[1]' but argument is of type >>> 'struct __va_list_tag **' >>> _printf_i (struct _reent *data, struct _prt_data_t *pdata, FILE *fp, >>> >>> >>> It looks like nano written without taking in mind such targets. Here I >>> found workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 >>> that's working. >>> >>> I'm attaching a patch. >>> >>> Alex >> >> Pushed. >> >> >> Thanks, >> Corinna >> >
Sorry for my other email not replying to this, when I started writing it I hadn't seen your email yet. Anyhow, I suggested a change to your patch there at the end, if you could give that a try to see if it works for you too, then we could (at least for now) maybe get away with it. Cheers, Andre On 24/01/18 16:02, Alexander Fedotov wrote: > Hello Andre > Yes indeed this fix unfortunately broke an ARM port. I have no idea > why this builtins doesn't work on gcc for arm. Best way I believe > right now is to revert this commit. > > Alex > > On Tue, Jan 23, 2018 at 5:04 PM, Andre Vieira (lists) > <Andre.SimoesDiasVieira@arm.com> wrote: >> Hi Alexander, >> >> This patch is causing our arm-none-eabi-gcc newlib-nano builds to fail. >> >> It seems the _Generic isn't picking up the right type when ap is of type >> va_list. We get the following error: >> newlib/libc/stdio/nano-vfscanf.c:430:2: error: cannot convert to a >> pointer type >> ret = _scanf_chars (rptr, &scan_data, fp, va_ptr(ap)); >> ^~~ >> newlib/libc/stdio/nano-vfscanf.c:432:2: error: cannot convert to a >> pointer type >> ret = _scanf_i (rptr, &scan_data, fp, va_ptr(ap)); >> ^~~ >> newlib/libc/stdio/nano-vfscanf.c:435:2: error: cannot convert to a >> pointer type >> ret = _scanf_float (rptr, &scan_data, fp, va_ptr(ap)); >> >> >> A reduced test-case, see: >> >> #include <stdio.h> >> extern void bar(va_list *ap); >> void foo(va_list ap) { >> bar(_Generic(&(ap), va_list *: &(ap), default: (va_list *)(ap))); >> } >> >> Note that va_list for our toolchain is defined as gcc's __builtin_va_list. >> >> I have tried your other definitions of va_ptr too and none of them seem >> to work. How do you suggest we proceed? >> >> Cheers, >> Andre >> >> >> >> On 08/01/18 10:07, Corinna Vinschen wrote: >>> On Dec 25 16:39, Alexander Fedotov wrote: >>>> Hi >>>> >>>> I'm experienced a strange printf() for float variables behaviour with >>>> Nano version while regular is fine. It just prins out a garbage (even >>>> with enabled -u _printf_float). After some digging I've managed to >>>> track down issue until this line: >>>> >>>> n = _printf_float (data, &prt_data, fp, pfunc, &ap); >>>> >>>> >>>> Moreover there are number of warnings also in build log: >>>> >>>> src_newlib/newlib/libc/stdio/nano-vfprintf.c -o lib_a-nano-svfprintf.o >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c: In >>>> function '_svfprintf_r': >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:645:55: >>>> warning: passing argument 5 of '_printf_float' from incompatible >>>> pointer type >>>> n = _printf_float (data, &prt_data, fp, pfunc, &ap); >>>> ^ >>>> In file included from >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:228:1: >>>> note: expected 'struct __va_list_tag (*)[1]' but argument is of type >>>> 'struct __va_list_tag **' >>>> _printf_float (struct _reent *data, >>>> ^ >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:650:45: >>>> warning: passing argument 5 of '_printf_i' from incompatible pointer >>>> type >>>> n = _printf_i (data, &prt_data, fp, pfunc, &ap); >>>> ^ >>>> In file included from >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:221:1: >>>> note: expected 'struct __va_list_tag (*)[1]' but argument is of type >>>> 'struct __va_list_tag **' >>>> _printf_i (struct _reent *data, struct _prt_data_t *pdata, FILE *fp, >>>> >>>> >>>> It looks like nano written without taking in mind such targets. Here I >>>> found workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 >>>> that's working. >>>> >>>> I'm attaching a patch. >>>> >>>> Alex >>> >>> Pushed. >>> >>> >>> Thanks, >>> Corinna >>> >> > > >
Sure, I can check fix on my side. Other way is to fix original issue from where this workaround comes https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557. But seems nobody cares it. Alex On Wed, 24 Jan 2018 at 20:46, Andre Vieira (lists) < Andre.SimoesDiasVieira@arm.com> wrote: > Sorry for my other email not replying to this, when I started writing it > I hadn't seen your email yet. > > Anyhow, I suggested a change to your patch there at the end, if you > could give that a try to see if it works for you too, then we could (at > least for now) maybe get away with it. > > Cheers, > Andre > > On 24/01/18 16:02, Alexander Fedotov wrote: > > Hello Andre > > Yes indeed this fix unfortunately broke an ARM port. I have no idea > > why this builtins doesn't work on gcc for arm. Best way I believe > > right now is to revert this commit. > > > > Alex > > > > On Tue, Jan 23, 2018 at 5:04 PM, Andre Vieira (lists) > > <Andre.SimoesDiasVieira@arm.com> wrote: > >> Hi Alexander, > >> > >> This patch is causing our arm-none-eabi-gcc newlib-nano builds to fail. > >> > >> It seems the _Generic isn't picking up the right type when ap is of type > >> va_list. We get the following error: > >> newlib/libc/stdio/nano-vfscanf.c:430:2: error: cannot convert to a > >> pointer type > >> ret = _scanf_chars (rptr, &scan_data, fp, va_ptr(ap)); > >> ^~~ > >> newlib/libc/stdio/nano-vfscanf.c:432:2: error: cannot convert to a > >> pointer type > >> ret = _scanf_i (rptr, &scan_data, fp, va_ptr(ap)); > >> ^~~ > >> newlib/libc/stdio/nano-vfscanf.c:435:2: error: cannot convert to a > >> pointer type > >> ret = _scanf_float (rptr, &scan_data, fp, va_ptr(ap)); > >> > >> > >> A reduced test-case, see: > >> > >> #include <stdio.h> > >> extern void bar(va_list *ap); > >> void foo(va_list ap) { > >> bar(_Generic(&(ap), va_list *: &(ap), default: (va_list *)(ap))); > >> } > >> > >> Note that va_list for our toolchain is defined as gcc's > __builtin_va_list. > >> > >> I have tried your other definitions of va_ptr too and none of them seem > >> to work. How do you suggest we proceed? > >> > >> Cheers, > >> Andre > >> > >> > >> > >> On 08/01/18 10:07, Corinna Vinschen wrote: > >>> On Dec 25 16:39, Alexander Fedotov wrote: > >>>> Hi > >>>> > >>>> I'm experienced a strange printf() for float variables behaviour with > >>>> Nano version while regular is fine. It just prins out a garbage (even > >>>> with enabled -u _printf_float). After some digging I've managed to > >>>> track down issue until this line: > >>>> > >>>> n = _printf_float (data, &prt_data, fp, pfunc, &ap); > >>>> > >>>> > >>>> Moreover there are number of warnings also in build log: > >>>> > >>>> src_newlib/newlib/libc/stdio/nano-vfprintf.c -o lib_a-nano-svfprintf.o > >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c: In > >>>> function '_svfprintf_r': > >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:645:55: > >>>> warning: passing argument 5 of '_printf_float' from incompatible > >>>> pointer type > >>>> n = _printf_float (data, &prt_data, fp, pfunc, &ap); > >>>> > ^ > >>>> In file included from > >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: > >>>> > ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:228:1: > >>>> note: expected 'struct __va_list_tag (*)[1]' but argument is of type > >>>> 'struct __va_list_tag **' > >>>> _printf_float (struct _reent *data, > >>>> ^ > >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:650:45: > >>>> warning: passing argument 5 of '_printf_i' from incompatible pointer > >>>> type > >>>> n = _printf_i (data, &prt_data, fp, pfunc, &ap); > >>>> ^ > >>>> In file included from > >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: > >>>> > ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:221:1: > >>>> note: expected 'struct __va_list_tag (*)[1]' but argument is of type > >>>> 'struct __va_list_tag **' > >>>> _printf_i (struct _reent *data, struct _prt_data_t *pdata, FILE *fp, > >>>> > >>>> > >>>> It looks like nano written without taking in mind such targets. Here I > >>>> found workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 > >>>> that's working. > >>>> > >>>> I'm attaching a patch. > >>>> > >>>> Alex > >>> > >>> Pushed. > >>> > >>> > >>> Thanks, > >>> Corinna > >>> > >> > > > > > > > > -- Best regards, AF
On 01/24/2018 11:46 AM, Andre Vieira (lists) wrote: > Hi, > > I looked a bit further into this and I can't reproduce this behavior for > the i386 backend. So I had a look through GCC's parser implementation > for _Generic and it seems GCC evaluates the expressions in each matching > case, that is to say it will also parse the default case. In arm, the > type of va_list is a struct, since it is invalid to cast structs to > pointers, the c-parser will error out when it parses this cast in the > default case. For an i386 gcc, and I'm guessing your case is the same, > the type of va_list can be cast to a pointer type, so it parses it > without errors. > > I don't know if parsing the expression of default if another case has > matched is intended behavior. I will investigate this further and if I > can convince myself this is wrong behavior I'll chase it with upstream gcc. > The final draft of the C11 standard, which I assume was not changed in the final release, does say that only the chosen expression is evaluated. (Which is as it must be. If it is choosing function names, for example, it can hardly evaluate a non-chosen option, as that means calling the function. The example they give is actually choosing a function.) A cast is an expression, so it appears that you do need to chase it with upstream GCC. It obviously has to parse each selection, but it must only evaluate one. Craig
On 2018-01-24 11:25, Craig Howland wrote: > On 01/24/2018 11:46 AM, Andre Vieira (lists) wrote: >> I looked a bit further into this and I can't reproduce this behavior for >> the i386 backend. So I had a look through GCC's parser implementation for >> _Generic and it seems GCC evaluates the expressions in each matching case, >> that is to say it will also parse the default case. In arm, the type of >> va_list is a struct, since it is invalid to cast structs to pointers, the >> c-parser will error out when it parses this cast in the default case. For >> an i386 gcc, and I'm guessing your case is the same, the type of va_list >> can be cast to a pointer type, so it parses it without errors. >> >> I don't know if parsing the expression of default if another case has >> matched is intended behavior. I will investigate this further and if I can >> convince myself this is wrong behavior I'll chase it with upstream gcc. >> > The final draft of the C11 standard, which I assume was not changed in the > final release, does say that only the chosen expression is evaluated. (Which > is as it must be. If it is choosing function names, for example, it can > hardly evaluate a non-chosen option, as that means calling the function. The > example they give is actually choosing a function.) A cast is an expression, > so it appears that you do need to chase it with upstream GCC. It obviously > has to parse each selection, but it must only evaluate one. FYI for _Generic definition and issues see: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf [CD] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1650.htm [DR original] http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_423.htm [DR discussion] https://gcc.gnu.org/ml/gcc-patches/2016-05/msg01054.html [GCC response] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1930.htm [followup] The official standard agrees with you at the end of #3, but see note (91 below; selectively quoting from ISO/IEC 9899:2011[2012] thru TC3: " 6 A generic selection is a primary expression. Its type and value depend on the selected generic association, as detailed in the following subclause. Forward references: declarations (6.7). 6.5.1.1 Generic selection Syntax 1 generic-selection: _Generic ( assignment-expression , generic-assoc-list ) generic-assoc-list: generic-association generic-assoc-list , generic-association generic-association: type-name : assignment-expression default : assignment-expression 91) Thus, an undeclared identifier is a violation of the syntax. Constraints 2 A generic selection shall have no more than one default generic association. The type name in a generic association shall specify a complete object type other than a variably modified type. No two generic associations in the same generic selection shall specify compatible types. The controlling expression of a generic selection shall have type compatible with at most one of the types named in its generic association list. If a generic selection has no default generic association, its controlling expression shall have type compatible with exactly one of the types named in its generic association list. Semantics 3 The controlling expression of a generic selection is not evaluated. If a generic selection has a generic association with a type name that is compatible with the type of the controlling expression, then the result expression of the generic selection is the expression in that generic association. Otherwise, the result expression of the generic selection is the expression in the default generic association. None of the expressions from any other generic association of the generic selection is evaluated. 4 The type and value of a generic selection are identical to those of its result expression. It is an lvalue, a function designator, or a void expression if its result expression is, respectively, an lvalue, a function designator, or a void expression. 5 EXAMPLE The cbrt type-generic macro could be implemented as follows: #define cbrt(X) _Generic((X), \ long double: cbrtl, \ default: cbrt, \ float: cbrtf \ )(X) " -- Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada
On Wed, 24 Jan 2018, Craig Howland wrote: > The final draft of the C11 standard, which I assume was not changed in the > final release, does say that only the chosen expression is evaluated. (Which Evaluated means executed, with all the associated side-effects, at runtime if the _Generic expression is executed at runtime. All expressions - including the assignment-expressions that appear in the _Generic syntax - must always meet the syntactic and semantic constraints (for example, the constraints on valid casts). This applies to unevaluated expressions inside _Generic just as it does to unevaluated expressions inside sizeof. -- Joseph S. Myers joseph@codesourcery.com
Well if this requires a much of effort I would rather propose to to wrap up these ifdef's by checking architecture. Like #if defined(_PPC_) || defined (__x86_64__) || defined (__amd64__) || defined (__i386__) etc On Wed, Jan 24, 2018 at 8:49 PM, Alexander Fedotov <alfedotov@gmail.com> wrote: > Sure, I can check fix on my side. > > Other way is to fix original issue from where this workaround comes > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557. But seems nobody cares > it. > > Alex > > On Wed, 24 Jan 2018 at 20:46, Andre Vieira (lists) > <Andre.SimoesDiasVieira@arm.com> wrote: >> >> Sorry for my other email not replying to this, when I started writing it >> I hadn't seen your email yet. >> >> Anyhow, I suggested a change to your patch there at the end, if you >> could give that a try to see if it works for you too, then we could (at >> least for now) maybe get away with it. >> >> Cheers, >> Andre >> >> On 24/01/18 16:02, Alexander Fedotov wrote: >> > Hello Andre >> > Yes indeed this fix unfortunately broke an ARM port. I have no idea >> > why this builtins doesn't work on gcc for arm. Best way I believe >> > right now is to revert this commit. >> > >> > Alex >> > >> > On Tue, Jan 23, 2018 at 5:04 PM, Andre Vieira (lists) >> > <Andre.SimoesDiasVieira@arm.com> wrote: >> >> Hi Alexander, >> >> >> >> This patch is causing our arm-none-eabi-gcc newlib-nano builds to fail. >> >> >> >> It seems the _Generic isn't picking up the right type when ap is of >> >> type >> >> va_list. We get the following error: >> >> newlib/libc/stdio/nano-vfscanf.c:430:2: error: cannot convert to a >> >> pointer type >> >> ret = _scanf_chars (rptr, &scan_data, fp, va_ptr(ap)); >> >> ^~~ >> >> newlib/libc/stdio/nano-vfscanf.c:432:2: error: cannot convert to a >> >> pointer type >> >> ret = _scanf_i (rptr, &scan_data, fp, va_ptr(ap)); >> >> ^~~ >> >> newlib/libc/stdio/nano-vfscanf.c:435:2: error: cannot convert to a >> >> pointer type >> >> ret = _scanf_float (rptr, &scan_data, fp, va_ptr(ap)); >> >> >> >> >> >> A reduced test-case, see: >> >> >> >> #include <stdio.h> >> >> extern void bar(va_list *ap); >> >> void foo(va_list ap) { >> >> bar(_Generic(&(ap), va_list *: &(ap), default: (va_list *)(ap))); >> >> } >> >> >> >> Note that va_list for our toolchain is defined as gcc's >> >> __builtin_va_list. >> >> >> >> I have tried your other definitions of va_ptr too and none of them seem >> >> to work. How do you suggest we proceed? >> >> >> >> Cheers, >> >> Andre >> >> >> >> >> >> >> >> On 08/01/18 10:07, Corinna Vinschen wrote: >> >>> On Dec 25 16:39, Alexander Fedotov wrote: >> >>>> Hi >> >>>> >> >>>> I'm experienced a strange printf() for float variables behaviour with >> >>>> Nano version while regular is fine. It just prins out a garbage (even >> >>>> with enabled -u _printf_float). After some digging I've managed to >> >>>> track down issue until this line: >> >>>> >> >>>> n = _printf_float (data, &prt_data, fp, pfunc, &ap); >> >>>> >> >>>> >> >>>> Moreover there are number of warnings also in build log: >> >>>> >> >>>> src_newlib/newlib/libc/stdio/nano-vfprintf.c -o >> >>>> lib_a-nano-svfprintf.o >> >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c: In >> >>>> function '_svfprintf_r': >> >>>> >> >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:645:55: >> >>>> warning: passing argument 5 of '_printf_float' from incompatible >> >>>> pointer type >> >>>> n = _printf_float (data, &prt_data, fp, pfunc, &ap); >> >>>> >> >>>> ^ >> >>>> In file included from >> >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: >> >>>> >> >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:228:1: >> >>>> note: expected 'struct __va_list_tag (*)[1]' but argument is of type >> >>>> 'struct __va_list_tag **' >> >>>> _printf_float (struct _reent *data, >> >>>> ^ >> >>>> >> >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:650:45: >> >>>> warning: passing argument 5 of '_printf_i' from incompatible pointer >> >>>> type >> >>>> n = _printf_i (data, &prt_data, fp, pfunc, &ap); >> >>>> ^ >> >>>> In file included from >> >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:169:0: >> >>>> >> >>>> ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf_local.h:221:1: >> >>>> note: expected 'struct __va_list_tag (*)[1]' but argument is of type >> >>>> 'struct __va_list_tag **' >> >>>> _printf_i (struct _reent *data, struct _prt_data_t *pdata, FILE *fp, >> >>>> >> >>>> >> >>>> It looks like nano written without taking in mind such targets. Here >> >>>> I >> >>>> found workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 >> >>>> that's working. >> >>>> >> >>>> I'm attaching a patch. >> >>>> >> >>>> Alex >> >>> >> >>> Pushed. >> >>> >> >>> >> >>> Thanks, >> >>> Corinna >> >>> >> >> >> > >> > >> > >> > -- > Best regards, > AF -- Best regards, AF
On 12/25/2017 07:39 AM, Alexander Fedotov wrote: > Hi > > I'm experienced a strange printf() for float variables behaviour with > Nano version while regular is fine. It just prins out a garbage (even > with enabled -u _printf_float). After some digging I've managed to > track down issue until this line: > > n = _printf_float (data, &prt_data, fp, pfunc, &ap); > > > Moreover there are number of warnings also in build log: > > src_newlib/newlib/libc/stdio/nano-vfprintf.c -o lib_a-nano-svfprintf.o > ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c: In > function '_svfprintf_r': > ../../../../../../src_newlib/newlib/libc/stdio/nano-vfprintf.c:645:55: > warning: passing argument 5 of '_printf_float' from incompatible > pointer type > n = _printf_float (data, &prt_data, fp, pfunc, &ap); > ^ One possibility for a workaround that I've seen used in other projects is to do a va_copy() and pass a pointer to the copy rather than the original ap passed in as a parameter. Here's a thread from the qemu list: https://lists.gnu.org/archive/html/qemu-devel/2017-08/msg00605.html https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg00171.html and where the va_copy() code is used in practice: https://git.qemu.org/?p=qemu.git;a=blob;f=tests/libqtest.c;h=0ec8af292;hb=2077fef9#l472 in order to call a function taking va_list *. 472 void qmp_fd_sendv(int fd, const char *fmt, va_list ap) 473 { 474 va_list ap_copy; ... 484 485 /* Going through qobject ensures we escape strings properly. 486 * This seemingly unnecessary copy is required in case va_list 487 * is an array type. 488 */ 489 va_copy(ap_copy, ap); 490 qobj = qobject_from_jsonv(fmt, &ap_copy, &error_abort); 491 va_end(ap_copy); 492 -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
From 47ee6b7a46e6331ae0840a2262258d2c868ccbc5 Mon Sep 17 00:00:00 2001 From: Alexander Fedotov <alfedotov@gmail.com> Date: Mon, 25 Dec 2017 16:28:22 +0300 Subject: [PATCH] fix incompatible pointer type for va_list in nano versions of printf and scanf for target like PowerPC --- newlib/libc/stdio/nano-vfprintf.c | 14 ++++++++++++-- newlib/libc/stdio/nano-vfscanf.c | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/newlib/libc/stdio/nano-vfprintf.c b/newlib/libc/stdio/nano-vfprintf.c index e6604e7..663eb71 100644 --- a/newlib/libc/stdio/nano-vfprintf.c +++ b/newlib/libc/stdio/nano-vfprintf.c @@ -168,6 +168,16 @@ static char *rcsid = "$Id$"; #include "vfieeefp.h" #include "nano-vfprintf_local.h" + +/* GCC PR 14577 at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 */ +#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 __ssputs_r function is shared between all versions of vfprintf and vfwprintf. */ #ifdef STRING_ONLY @@ -633,12 +643,12 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap), } else { - n = _printf_float (data, &prt_data, fp, pfunc, &ap); + n = _printf_float (data, &prt_data, fp, pfunc, va_ptr(ap)); } } else #endif - n = _printf_i (data, &prt_data, fp, pfunc, &ap); + n = _printf_i (data, &prt_data, fp, pfunc, va_ptr(ap)); if (n == -1) goto error; diff --git a/newlib/libc/stdio/nano-vfscanf.c b/newlib/libc/stdio/nano-vfscanf.c index 564f291..6467e54 100644 --- a/newlib/libc/stdio/nano-vfscanf.c +++ b/newlib/libc/stdio/nano-vfscanf.c @@ -119,6 +119,15 @@ Supporting OS subroutines required: #include "../stdlib/local.h" #include "nano-vfscanf_local.h" +/* GCC PR 14577 at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 */ +#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 + #define VFSCANF vfscanf #define _VFSCANF_R _vfscanf_r #define __SVFSCANF __svfscanf @@ -424,12 +433,12 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), } ret = 0; if (scan_data.code < CT_INT) - ret = _scanf_chars (rptr, &scan_data, fp, &ap); + ret = _scanf_chars (rptr, &scan_data, fp, va_ptr(ap)); else if (scan_data.code < CT_FLOAT) - ret = _scanf_i (rptr, &scan_data, fp, &ap); + ret = _scanf_i (rptr, &scan_data, fp, va_ptr(ap)); #ifdef FLOATING_POINT else if (_scanf_float) - ret = _scanf_float (rptr, &scan_data, fp, &ap); + ret = _scanf_float (rptr, &scan_data, fp, va_ptr(ap)); #endif if (ret == MATCH_FAILURE) -- 2.7.4