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. --- conform/data/wchar.h-data | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'conform/data/wchar.h-data') diff --git a/conform/data/wchar.h-data b/conform/data/wchar.h-data index e414651a33..424c59c819 100644 --- a/conform/data/wchar.h-data +++ b/conform/data/wchar.h-data @@ -59,17 +59,17 @@ function wint_t towlower (wint_t) function wint_t towupper (wint_t) # endif function wint_t ungetwc (wint_t, FILE*) -function int vfwprintf (FILE*, const wchar_t*, __gnuc_va_list) +function int vfwprintf (FILE*, const wchar_t*, __va_list) # ifndef UNIX98 -function int vfwscanf (FILE*, const wchar_t*, __gnuc_va_list) +function int vfwscanf (FILE*, const wchar_t*, __va_list) # endif -function int vwprintf (const wchar_t*, __gnuc_va_list) +function int vwprintf (const wchar_t*, __va_list) # ifndef UNIX98 -function int vwscanf (const wchar_t*, __gnuc_va_list) +function int vwscanf (const wchar_t*, __va_list) # endif -function int vswprintf (wchar_t*, size_t, const wchar_t*, __gnuc_va_list) +function int vswprintf (wchar_t*, size_t, const wchar_t*, __va_list) # ifndef UNIX98 -function int vswscanf (const wchar_t*, const wchar_t*, __gnuc_va_list) +function int vswscanf (const wchar_t*, const wchar_t*, __va_list) # endif # if defined XOPEN2K8 || defined POSIX2008 function {wchar_t*} wcpcpy (wchar_t*, const wchar_t*) -- cgit 1.4.1