[llvm-dev] va_arg macro

John Brawn via llvm-dev llvm-dev at lists.llvm.org
Fri Oct 5 08:52:25 PDT 2018


> I've found that clang v7 treats va_arg, at least differently from gcc
> (and c standard says it should accept argument with one void). Clang
> does not accept va_arg(...,void).

GCC from version 6 onwards (and perhaps earlier) also gives an error
for this. And I don't see anything in the C standard to say it should
accept void as an argument: looking at section 7.15.1.1 paragraph 2
of C99 it says:

 If there is no actual next argument, or if type is not compatible with
 the type of the actual next argument (as promoted according to the
 default argument promotions), the behavior is undefined, except for the
 following cases:
  - one type is a signed integer type, the other type is the corresponding
    unsigned integer type, and the value is representable in both types;
  - one type is pointer to void and the other is a pointer to a character
    type.

void is not compatible with any type, so doing va_arg(something, void) is
undefined behaviour (though I wouldn't be surprised if something elsewhere
makes it invalid to use an incomplete type here for some other reason).
If it were to be permitted I also don't see anything meaningful that the
compiler could do with such a va_arg call, other than to say "void = nothing
therefore va_arg(something, void) means don't consume an argument" in
which case the solution is just to remove the va_arg call.

John

> -----Original Message-----
> From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] On Behalf Of
> Qiantan Hong via llvm-dev
> Sent: 04 October 2018 23:22
> To: llvm-dev at lists.llvm.org
> Subject: [llvm-dev] va_arg macro
> 
> Hi,
> 
> New here, not mean to be spam. If I'm doing something wrong please just
> tell me.
> 
> I've found that clang v7 treats va_arg, at least differently from gcc
> (and c standard says it should accept argument with one void). Clang
> does not accept va_arg(...,void).
> When I was trying to build redis I got this:
> 
> hiredis.c:799:31: error: second argument to 'va_arg' is of incomplete
> type
>       'void'
>                     va_arg(ap,void);
> 
> I then write a work around by replacing `#define va_arg(ap, type)
> __builtin_va_arg(ap, type)` with those line to stdarg.h (In my
> environment, the path is
> /usr/local/Cellar/llvm/7.0.0/lib/clang/7.0.0/include):
> 
> #define __kscarlet_transform_cat_(x,y) x##y
> #define __kscarlet_transform_cat(x,y) __kscarlet_transform_cat_(x,y)
> #define __kscarlet_transform_void() )()__kscarlet_transform_n_(
> #define __kscarlet_transform_e(...) __VA_ARGS__
> #define __kscarlet_transform_e_(...) __VA_ARGS__
> #define __kscarlet_transform_n(...)
> #define __kscarlet_transform_n2(...) char
> #define __kscarlet_transform_n_(...) __kscarlet_transform_n2
> #define __kscarlet_transform_void_(...) __kscarlet_transform_e
> #define va_arg(ap,type)
> __builtin_va_arg(ap,__kscarlet_transform_e_(__kscarlet_transform_void_
> __kscarlet_transform_n()(__kscarlet_transform_cat(
> __kscarlet_transform_,type)()))(type))
> 
> This solves the problem, though it polluted global namespace. Do you
> have any idea to patch it / whether it should be patched?
> 
> Best,
> BlueFlo0d
> 
> 



More information about the llvm-dev mailing list