From ee57733099e3d12bc0a822a2d56f4e5b1b2cdae1 Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Wed, 29 May 2019 14:23:32 -0400 Subject: Don’t rely on stddef.h or stdarg.h for individual type definitions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the course of developing earlier patches in this series I discovered that clang’s stddef.h does not implement the __need_* convention correctly: in C++, under some circumstances __need_NULL will also cause a definition of nullptr_t, and when the “modules” feature is enabled, all of the __need macros are ignored and all of stddef.h is exposed. (I’m not sure how to actually make either of these things happen, I discovered the problem by reading the file.) Worse, clang’s stdarg.h does not implement __need___va_list *at all*; including its stdarg.h will always expose all of its definitions. These are bugs in clang but it seems prudent to work around them, and the simplest way to do so is to have the bits/types/ headers introduced in the previous patch make definitions themselves, when possible. For size_t, ptrdiff_t, and wchar_t, we can use the predefined macros __SIZE_TYPE__, __PTRDIFF_TYPE__, and __WCHAR_TYPE__, when available, falling back to the old approach. For __gnuc_va_list, we have a whitelist of compilers known to provide __builtin_va_list, falling back to the old approach. NULL and va_list are defined ab initio. An additional complication is that we must be able to tell stddef.h and stdarg.h _not_ to define again things we have already defined. It appears to me, based on inspection of clang, GCC, and icc stddef.h and stdarg.h, that we can use the macros _SIZE_T, _PTRDIFF_T, _WCHAR_T, _VA_LIST, and __GNUC_VA_LIST to accomplish this. Since we are no longer relying on stdarg.h to define an implementation-namespace alias for us, I thought it would make sense also to stop calling it __gnuc_va_list. The bulk of this patch is a mechanical substitution of __va_list for __gnuc_va_list throughout our headers. Copyright boilerplate is added to stdlib/bits/NULL.h and stdlib/bits/types/*.h because they now contain enough commentary and code that they could plausibly be copyrightable. * stdlib/bits/NULL.h: Do not use stddef.h to define NULL. Define NULL ab initio if not already defined, as `((void *)0)` for C, and either `__null` or 0 for C++, depending on compiler support. * stdlib/bits/types/__va_list.h: If __builtin_va_list is known to be available, use it to define __va_list without including stdarg.h. Otherwise use __need___va_list to request a definition of __gnuc_va_list and nothing else from stdarg.h, then use that to define __va_list. * stdlib/bits/types/va_list.h: Use __va_list, not __gnuc_va_list, to define va_list. Improve commentary. * stdlib/bits/types/ptrdiff_t.h: If __PTRDIFF_TYPE__ is defined, use it to define ptrdiff_t without including stddef.h. Otherwise use __need_ptrdiff_t to request a definition of ptrdiff_t and nothing else from stddef.h. Use _PTRDIFF_T as guard macro to match behavior of common stddef.h implementations. * stdlib/bits/types/size_t.h: Similarly for size_t, with __SIZE_TYPE__, __need_size_t, and _SIZE_T. * stdlib/bits/types/wchar_t.h: Similarly for wchar_t, with __WCHAR_TYPE__, __need_wchar_t, and _WCHAR_T. If __cplusplus is defined, do nothing; wchar_t is built-in in C++. * conform/data/stdio.h-data, conform/data/wchar.h-data * include/err.h, include/stdio.h, include/syslog.h, include/wchar.h * libio/bits/stdio.h, libio/bits/stdio2.h, libio/iolibio.h * libio/libio.h, libio/stdio.h, libio/vwprintf.c, misc/bits/syslog.h * misc/err.c, misc/err.h, misc/syslog.h, stdio-common/printf.h * sysdeps/ieee754/ldbl-opt/nldbl-compat.c * sysdeps/ieee754/ldbl-opt/nldbl-compat.h * wcsmbs/bits/wchar2.h, wcsmbs/wchar.h: Replace all uses of __gnuc_va_list with __va_list. * scripts/check-obsolete-constructs.py (HEADER_ALLOWED_INCLUDES): bits/NULL.h is no longer allowed to include stddef.h. --- sysdeps/ieee754/ldbl-opt/nldbl-compat.c | 8 ++++---- sysdeps/ieee754/ldbl-opt/nldbl-compat.h | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'sysdeps') diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c index ef5ab18fe2..d5e8833c61 100644 --- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c +++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c @@ -1036,14 +1036,14 @@ __nldbl_errx (int status, const char *format, ...) } void -__nldbl_verr (int status, const char *format, __gnuc_va_list ap) +__nldbl_verr (int status, const char *format, __va_list ap) { __vwarn_internal (format, ap, PRINTF_LDBL_IS_DBL); exit (status); } void -__nldbl_verrx (int status, const char *format, __gnuc_va_list ap) +__nldbl_verrx (int status, const char *format, __va_list ap) { __vwarnx_internal (format, ap, PRINTF_LDBL_IS_DBL); exit (status); @@ -1062,13 +1062,13 @@ __nldbl_warnx (const char *format, ...) } void -__nldbl_vwarn (const char *format, __gnuc_va_list ap) +__nldbl_vwarn (const char *format, __va_list ap) { __vwarn_internal (format, ap, PRINTF_LDBL_IS_DBL); } void -__nldbl_vwarnx (const char *format, __gnuc_va_list ap) +__nldbl_vwarnx (const char *format, __va_list ap) { __vwarnx_internal (format, ap, PRINTF_LDBL_IS_DBL); } diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.h b/sysdeps/ieee754/ldbl-opt/nldbl-compat.h index c2a01fcb9b..74ecdf50f8 100644 --- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.h +++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.h @@ -103,23 +103,23 @@ extern ssize_t __nldbl___vstrfmon_l (char *, size_t, locale_t, const char *, /* These don't use __typeof because they were not declared by the headers, since we don't compile with _FORTIFY_SOURCE. */ extern int __nldbl___vfprintf_chk (FILE *__restrict, int, - const char *__restrict, __gnuc_va_list); + const char *__restrict, __va_list); extern int __nldbl___vfwprintf_chk (FILE *__restrict, int, - const wchar_t *__restrict, __gnuc_va_list); + const wchar_t *__restrict, __va_list); extern int __nldbl___vsprintf_chk (char *__restrict, int, size_t, - const char *__restrict, __gnuc_va_list) + const char *__restrict, __va_list) __THROW; extern int __nldbl___vsnprintf_chk (char *__restrict, size_t, int, size_t, - const char *__restrict, __gnuc_va_list) + const char *__restrict, __va_list) __THROW; extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t, - const wchar_t *__restrict, __gnuc_va_list) + const wchar_t *__restrict, __va_list) __THROW; -extern int __nldbl___vasprintf_chk (char **, int, const char *, __gnuc_va_list) +extern int __nldbl___vasprintf_chk (char **, int, const char *, __va_list) __THROW; -extern int __nldbl___vdprintf_chk (int, int, const char *, __gnuc_va_list); +extern int __nldbl___vdprintf_chk (int, int, const char *, __va_list); extern int __nldbl___obstack_vprintf_chk (struct obstack *, int, const char *, - __gnuc_va_list) __THROW; + __va_list) __THROW; extern void __nldbl___vsyslog_chk (int, int, const char *, va_list); /* The original declarations of these were hidden by the including -- cgit 1.4.1