Date: Thu, 17 May 2001 14:34:04 +0200 From: Cyrille Artho <cartho@silmaril.org> To: bugs@freebsd.org Cc: Ernst de Haan <ernst@jollem.com> Subject: Insufficient type casts in stdargs.h Message-ID: <3B03C53C.349F9491@silmaril.org>
next in thread | raw e-mail | index | archive | help
Hi,
in FreeBSD 4.3's stdargs.h, the macro va_arg does not contain enough
type casts. As a result, gcc 2.95.3 rejects using va_arg with void*
arguments.
The GNU stdargs.h contains extra type casts, allowing this. I rewrote
the BSD to include extra type casts, fixing now problems with void*
va_arg arguments:
Original macro in /usr/include/stdarg.h, line 53:
#define va_arg(ap, type) \
(*(type *)((ap) += __va_size(type), (ap) - __va_size(type)))
My suggestion:
#define va_arg(ap, type) \
(*(type *)((ap) = (type *)((char *)ap + __va_size(type)), \
(type *)(((char *)ap) - __va_size(type))))
This adds three extra type casts, two intermediate ones to char* and one
more to type*. Moreover, I had to write out the += operator as it is not
allowed with void* anymore.
Please review this patch carefully, as it is a critical header file, and
not very easy to read - so I could have made an error, or there may be a
better way to fix the problem.
Originally, this compiler problem was discovered by Ernst de Haan, when
he tried to compile my Java program checker Jlint
(http://artho.com/jlint/). I include the full information about the line
of code that did not compile below:
Original source code:
parameter[n_parameters++] = va_arg(ap, void*);
-------------------------------------------------------------------------
Linux little endian systems:
#define va_arg(AP, TYPE)
\
(AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)),
\
*((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))
Expanded source code:
parameter[n_parameters++] = ( ap = (__gnuc_va_list) ((char *) ( ap ) +
(((sizeof ( void* ) + sizeof (int) - 1) / sizeof (int)) * sizeof
(int)) ), *(( void* *) (void *) ((char *) ( ap ) - (((sizeof (
void* ) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) ))) ;
-------------------------------------------------------------------------
FreeBSD:
#define va_arg(ap, type) \
(*(type *)((ap) += __va_size(type), (ap) - __va_size(type)))
Expanded source code:
parameter[n_parameters++] = (*( void* *)(( ap ) += (((sizeof( void*
) + sizeof(int) - 1) / sizeof(int)) * sizeof(int)) , ( ap ) -
(((sizeof( void* ) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
))
jlint.cc:141: ANSI C++ forbids using pointer of type `void *' in
arithmetic
jlint.cc:141: ANSI C++ forbids using pointer of type `void *' in
arithmetic
Provisional fix:
#define va_arg(ap, type) \
(*(type *)((ap) = (type *)((char *)ap + __va_size(type)), \
(type *)(((char *)ap) - __va_size(type))))
--
Regards,
Cyrille Artho - http://artho.com/ - Tel. +41 - [0]1 - 632 09 88
If you go on with this nuclear arms race, all you are going to do is
make the rubble bounce.
-- Winston Churchill
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3B03C53C.349F9491>
