diff options
author | Zack Weinberg <zackw@panix.com> | 2019-05-29 14:23:32 -0400 |
---|---|---|
committer | Zack Weinberg <zackw@panix.com> | 2020-01-08 13:42:38 -0500 |
commit | ee57733099e3d12bc0a822a2d56f4e5b1b2cdae1 (patch) | |
tree | fec88df12537c3adb30770b4673b510542e47f94 /stdlib | |
parent | cb54252075282ed6ed171a5b0d8eb372c2b06522 (diff) | |
download | glibc-ee57733099e3d12bc0a822a2d56f4e5b1b2cdae1.zip glibc-ee57733099e3d12bc0a822a2d56f4e5b1b2cdae1.tar.gz glibc-ee57733099e3d12bc0a822a2d56f4e5b1b2cdae1.tar.bz2 |
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 'stdlib')
-rw-r--r-- | stdlib/bits/NULL.h | 49 | ||||
-rw-r--r-- | stdlib/bits/types/__va_list.h | 48 | ||||
-rw-r--r-- | stdlib/bits/types/ptrdiff_t.h | 48 | ||||
-rw-r--r-- | stdlib/bits/types/size_t.h | 48 | ||||
-rw-r--r-- | stdlib/bits/types/va_list.h | 31 | ||||
-rw-r--r-- | stdlib/bits/types/wchar_t.h | 53 |
6 files changed, 244 insertions, 33 deletions
diff --git a/stdlib/bits/NULL.h b/stdlib/bits/NULL.h index 79285bd..96b7556 100644 --- a/stdlib/bits/NULL.h +++ b/stdlib/bits/NULL.h @@ -1,8 +1,47 @@ -#ifndef _BITS_NULL_H -#define _BITS_NULL_H 1 +/* Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. -/* We rely on the compiler's stddef.h to define NULL for us. */ -#define __need_NULL -#include <stddef.h> + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* There is no consensus among compilers as to the proper guard macro + for having defined NULL specifically ... except NULL itself. */ +#ifndef NULL + +/* In C, ((void *)0) is the preferred choice for the expansion of + NULL, as it cannot be misinterpreted as an integer zero. */ +#ifndef __cplusplus +# define NULL ((void *)0) + +/* ((void *)0) cannot be used in C++. In C++2011 and later, nullptr + is the preferred alternative, but programs are to be encouraged to + migrate away from both bare 0 and NULL to nullptr, so we do not + define NULL as nullptr. Some compilers support an extension + keyword __null that will trigger diagnostics when used in a context + that expects an integer, but will also be treated as 0 for purposes + of diagnostics encouraging migration to nullptr. + + The complexity of this #if is because clang++ always pretends to be + G++ and may also pretend to be one of several different Windows + compilers. */ +#elif (defined __GNUG__ || defined __clang__) \ + && !defined _MSC_VER && !defined __MINGW32__ +# define NULL __null + +/* Otherwise a bare 0 will have to do. */ +#else +# define NULL 0 +#endif #endif diff --git a/stdlib/bits/types/__va_list.h b/stdlib/bits/types/__va_list.h index e3c53c3..ac5ab40 100644 --- a/stdlib/bits/types/__va_list.h +++ b/stdlib/bits/types/__va_list.h @@ -1,9 +1,47 @@ +/* Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + #ifndef ____va_list_defined -#define ____va_list_defined 1 -/* We rely on the compiler's stdarg.h to define __gnuc_va_list for us. */ -#define __need___va_list -#include <stdarg.h> -#undef __need___va_list +/* If __builtin_va_list is available, use it. There is no predefined + macro advertising the availability of this type. It is known to be + available in GCC 3.0 and later. It is also known to be available + in all released versions of clang. */ +#if defined __clang__ || (defined __GNUC__ && __GNUC__ >= 3) + +typedef __builtin_va_list __va_list; +#else + +/* Depending on the compiler, we may be able to persuade its stdarg.h + to define an implementation-namespace alias for va_list and nothing + else. If this feature is not available, exposing everything + defined by stdarg.h is better than not defining __va_list at all. */ +# define __need___va_list +# include <stdarg.h> +# undef __need___va_list + +# ifdef __GNUC_VA_LIST +typedef __gnuc_va_list __va_list; +# else +typedef va_list __va_list; +# endif +#endif + +/* This must not be defined until _after_ possibly including stdarg.h. */ +#define ____va_list_defined 1 #endif diff --git a/stdlib/bits/types/ptrdiff_t.h b/stdlib/bits/types/ptrdiff_t.h index 23a8b98..a1cb9d9 100644 --- a/stdlib/bits/types/ptrdiff_t.h +++ b/stdlib/bits/types/ptrdiff_t.h @@ -1,9 +1,45 @@ -#ifndef __ptrdiff_t_defined -#define __ptrdiff_t_defined 1 +/* Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. -/* We rely on the compiler's stddef.h to define ptrdiff_t for us. */ -#define __need_ptrdiff_t -#include <stddef.h> -#undef __need_ptrdiff_t + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* The guard macro for this header must match the guard macro used by + the compiler's stddef.h for ptrdiff_t specifically. + GCC's stddef.h checks a long list of other macros as well as this + one, in order to accommodate many different C libraries, but clang's + stddef.h only looks for this macro. Other compilers can reasonably + be expected to look for this macro as well. */ +#ifndef _PTRDIFF_T + +#ifdef __PTRDIFF_TYPE__ + +/* If the predefined macro __PTRDIFF_TYPE__ is available, use it. */ +typedef __PTRDIFF_TYPE__ ptrdiff_t; + +#else + +/* Depending on the compiler, we may be able to persuade its stddef.h + to define ptrdiff_t and nothing else. If this feature is not + available, exposing everything defined by stddef.h is better than + not defining ptrdiff_t at all. */ +# define __need_ptrdiff_t +# include <stddef.h> +# undef __need_ptrdiff_t + +#endif + +/* This must not be defined until _after_ possibly including stddef.h. */ +#define _PTRDIFF_T #endif diff --git a/stdlib/bits/types/size_t.h b/stdlib/bits/types/size_t.h index e151458..827ede3 100644 --- a/stdlib/bits/types/size_t.h +++ b/stdlib/bits/types/size_t.h @@ -1,9 +1,45 @@ -#ifndef __size_t_defined -#define __size_t_defined 1 +/* Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. -/* We rely on the compiler's stddef.h to define size_t for us. */ -#define __need_size_t -#include <stddef.h> -#undef __need_size_t + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* The guard macro for this header must match the guard macro used by + the compiler's stddef.h for size_t specifically. + GCC's stddef.h checks a long list of other macros as well as this + one, in order to accommodate many different C libraries, but clang's + stddef.h only looks for this macro. Other compilers can reasonably + be expected to look for this macro as well. */ +#ifndef _SIZE_T + +#ifdef __SIZE_TYPE__ + +/* If the predefined macro __SIZE_TYPE__ is available, use it. */ +typedef __SIZE_TYPE__ size_t; + +#else + +/* Depending on the compiler, we may be able to persuade its stddef.h + to define size_t and nothing else. If this feature is not + available, exposing everything defined by stddef.h is better than + not defining size_t at all. */ +# define __need_size_t +# include <stddef.h> +# undef __need_size_t + +#endif + +/* This must not be defined until _after_ possibly including stddef.h. */ +#define _SIZE_T #endif diff --git a/stdlib/bits/types/va_list.h b/stdlib/bits/types/va_list.h index 6f3acac..6e1db79 100644 --- a/stdlib/bits/types/va_list.h +++ b/stdlib/bits/types/va_list.h @@ -1,6 +1,26 @@ -/* This guard macro needs to match the one used by at least gcc and - clang's stdarg.h to indicate that va_list, specifically, has been - defined. */ +/* Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* The guard macro for this header must match the guard macro used by + the compiler's stdarg.h for va_list specifically. + GCC's stdarg.h checks several other macros as well as this one, in + order to accommodate many different C libraries, but clang's + stdarg.h only looks for this macro. Other compilers can reasonably + be expected to look for this macro as well. */ #ifndef _VA_LIST #include <bits/types/__va_list.h> @@ -8,8 +28,9 @@ /* Check again, __va_list.h may not have been able to avoid including all of stdarg.h. */ # ifndef _VA_LIST -typedef __gnuc_va_list va_list; +typedef __va_list va_list; # endif -# define _VA_LIST +/* This must not be defined until _after_ possibly including stdarg.h. */ +# define _VA_LIST #endif diff --git a/stdlib/bits/types/wchar_t.h b/stdlib/bits/types/wchar_t.h index 1e44e15..ba0f94f 100644 --- a/stdlib/bits/types/wchar_t.h +++ b/stdlib/bits/types/wchar_t.h @@ -1,9 +1,50 @@ -#ifndef __wchar_t_defined -#define __wchar_t_defined 1 +/* Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. -/* We rely on the compiler's stddef.h to define wchar_t for us. */ -#define __need_wchar_t -#include <stddef.h> -#undef __need_wchar_t + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* The guard macro for this header must match the guard macro used by + the compiler's stddef.h for wchar_t specifically. + GCC's stddef.h checks a long list of other macros as well as this + one, in order to accommodate many different C libraries, but clang's + stddef.h only looks for this macro. Other compilers can reasonably + be expected to look for this macro as well. */ +#ifndef _WCHAR_T + +#ifdef __cplusplus +/* Do nothing; wchar_t is a built-in type and reserved word in C++. */ +#else + +# ifdef __WCHAR_TYPE__ + +/* If the predefined macro __WCHAR_TYPE__ is available, use it. */ +typedef __WCHAR_TYPE__ wchar_t; + +# else + +/* Depending on the compiler, we may be able to persuade its stddef.h + to define wchar_t and nothing else. If this feature is not + available, exposing everything defined by stddef.h is better than + not defining wchar_t at all. */ +# define __need_wchar_t +# include <stddef.h> +# undef __need_wchar_t + +# endif /* not __WCHAR_TYPE__ */ +#endif /* not __cplusplus */ + +/* This must not be defined until _after_ possibly including stddef.h. */ +#define _WCHAR_T #endif |