about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2019-05-29 14:23:32 -0400
committerZack Weinberg <zackw@panix.com>2020-01-08 13:42:38 -0500
commitee57733099e3d12bc0a822a2d56f4e5b1b2cdae1 (patch)
treefec88df12537c3adb30770b4673b510542e47f94 /sysdeps
parentcb54252075282ed6ed171a5b0d8eb372c2b06522 (diff)
downloadglibc-ee57733099e3d12bc0a822a2d56f4e5b1b2cdae1.tar.gz
glibc-ee57733099e3d12bc0a822a2d56f4e5b1b2cdae1.tar.xz
glibc-ee57733099e3d12bc0a822a2d56f4e5b1b2cdae1.zip
Don’t rely on stddef.h or stdarg.h for individual type definitions.
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.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-compat.c8
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-compat.h16
2 files changed, 12 insertions, 12 deletions
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