https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557

felix <felix.von.s at posteo dot de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |felix.von.s at posteo dot de

--- Comment #19 from felix <felix.von.s at posteo dot de> ---
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.

Reply via email to