This implements WG14 N2975 relaxing requirements for va_start (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2975.pdf), which does two things: 1) Allows the declaration of a variadic function without any named arguments. e.g., void f(...) is now valid, as in C++. 2) Modified the signature of the va_start macro to be a variadic macro that accepts one or more arguments; the second (and later) arguments are not expanded or evaluated. I followed the GCC implementation in terms of not modifying the behavior of `__builtin_va_start` (it still requires exactly two arguments), but this approach has led to several QoI issues that I've documented with FIXME comments in the test. Specifically, the requirement that we do not evaluate *or expand* the second and later arguments means it's no longer possible to issue diagnostics for compatibility with older C versions and C++. I am reaching out to folks in WG14 to see if we can get an NB comment to address these concerns (the US comment period has already closed, so I cannot file the comment myself), so the diagnostic behavior may change in the future. I took this opportunity to add some documentation for all the related builtins in this area, since there was no documentation for them yet. Differential Revision: https://reviews.llvm.org/D139436
52 lines
1.7 KiB
C++
52 lines
1.7 KiB
C++
/*===---- stdarg.h - Variable argument handling ----------------------------===
|
|
*
|
|
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
* See https://llvm.org/LICENSE.txt for license information.
|
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
*
|
|
*===-----------------------------------------------------------------------===
|
|
*/
|
|
|
|
#ifndef __STDARG_H
|
|
|
|
#ifndef __GNUC_VA_LIST
|
|
#define __GNUC_VA_LIST
|
|
typedef __builtin_va_list __gnuc_va_list;
|
|
#endif
|
|
|
|
#ifdef __need___va_list
|
|
#undef __need___va_list
|
|
#else
|
|
#define __STDARG_H
|
|
#ifndef _VA_LIST
|
|
typedef __builtin_va_list va_list;
|
|
#define _VA_LIST
|
|
#endif
|
|
|
|
/* FIXME: This is using the placeholder dates Clang produces for these macros
|
|
in C2x mode; switch to the correct values once they've been published. */
|
|
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L
|
|
/* C2x does not require the second parameter for va_start. */
|
|
#define va_start(ap, ...) __builtin_va_start(ap, 0)
|
|
#else
|
|
/* Versions before C2x do require the second parameter. */
|
|
#define va_start(ap, param) __builtin_va_start(ap, param)
|
|
#endif
|
|
#define va_end(ap) __builtin_va_end(ap)
|
|
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
|
|
|
/* GCC always defines __va_copy, but does not define va_copy unless in c99 mode
|
|
* or -ansi is not specified, since it was not part of C90.
|
|
*/
|
|
#define __va_copy(d,s) __builtin_va_copy(d,s)
|
|
|
|
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
|
|
(defined(__cplusplus) && __cplusplus >= 201103L) || \
|
|
!defined(__STRICT_ANSI__)
|
|
#define va_copy(dest, src) __builtin_va_copy(dest, src)
|
|
#endif
|
|
|
|
#endif /* __STDARG_H */
|
|
|
|
#endif /* not __STDARG_H */
|