Subject: standards/6923: va_start() macro can produce invalid C++ cope
To: None <gnats-bugs@gnats.netbsd.org>
From: Jaromir Dolecek <jdolecek@per4mance.cz>
List: netbsd-bugs
Date: 02/01/1999 16:06:43
>Number: 6923
>Category: standards
>Synopsis: va_start() macro can produce invalid C++ cope
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: gnats-admin (GNATS administrator)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Feb 1 07:20:01 1999
>Last-Modified:
>Originator: Jaromir Dolecek
>Organization:
ICS MU, Brno, Czech Republic
>Release: NetBSD-19981207
>Environment:
System: NetBSD jdolecek.per4mance.cz 1.3I NetBSD 1.3I (JDOLECEK) #0: Sun Jan 31 21:02:09 MET 1999 dolecek@jdolecek.per4mance.cz:/home/dolecek/tmp/kern-19990116/src/sys/arch/i386/compile/JDOLECEK i386
>Description:
va_start() macro can produce code, which fail to compile
under C++ (tested with gcc-2.7.2, egcs-1.1.1, MSVC++ 5.0),
if parameter ``last'' contains a cast, i.e. it's called as:
va_start(list, (const char *)foo);
the macro get's expanded to something containing
(va_start) &((const char *)foo) ....
on which c++ compiler chokes
non-lvalue in unary `&'
>How-To-Repeat:
> cat f.cpp
#include <stdarg.h>
void main(int argc, ...) {
va_list list;
va_start(list, (const int *)argc);
}
> g++ f.cpp
f.cpp: In function `int main(...)':
f.cpp:5: non-lvalue in unary `&'
>Fix:
Well, I don't know what the _real_ solution would be (I am
not a C++ fan at all), I don't even know if it's good C++ practice
to use a cast in va_start() macro. Using gcc builtin works, though.
It's also what other OSes do (I quickly scanned Solaris, Linux
and FreeBSD included). Not a perfect solution, but functional one.
Here is a patch for i386 <stdarg.h>:
--- stdarg.h.orig Mon Feb 1 15:37:10 1999
+++ stdarg.h Mon Feb 1 15:38:18 1999
@@ -45,8 +45,13 @@
#define __va_size(type) \
(((sizeof(type) + sizeof(long) - 1) / sizeof(long)) * sizeof(long))
+#ifdef __GNUC__
+#define va_start(ap, last) \
+ ((ap) = (va_list)__builtin_next_arg(last))
+#else
#define va_start(ap, last) \
((ap) = (va_list)(void *)&(last) + __va_size(last))
+#endif
#define va_arg(ap, type) \
(*(type *)(void *)((ap) += __va_size(type), (ap) - __va_size(type)))
>Audit-Trail:
>Unformatted: