From efb15adf1d62d6c6139d17a6b5b1cd5634677e0f Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 5 Aug 2018 14:06:08 +0200 Subject: [PATCH] Fix link error regarding 'rpl_environ' (regression from 2012-11-21). * m4/extern-inline.m4: Add more comments. * lib/warn-on-use.h (_GL_WARN_ON_USE_ATTRIBUTE): New macro. * lib/unistd.in.h (rpl_environ): Use it instead of _GL_WARN_ON_USE. * lib/math.in.h (_GL_WARN_REAL_FLOATING_DECL): Likewise. --- ChangeLog | 8 ++++++ lib/math.in.h | 42 ++++++++++++++--------------- lib/unistd.in.h | 4 +-- lib/warn-on-use.h | 64 ++++++++++++++++++++++++++++++--------------- m4/extern-inline.m4 | 16 ++++++++++-- 5 files changed, 88 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index eee980ac26..5d9b6bf417 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2018-08-05 Bruno Haible + + Fix link error regarding 'rpl_environ' (regression from 2012-11-21). + * m4/extern-inline.m4: Add more comments. + * lib/warn-on-use.h (_GL_WARN_ON_USE_ATTRIBUTE): New macro. + * lib/unistd.in.h (rpl_environ): Use it instead of _GL_WARN_ON_USE. + * lib/math.in.h (_GL_WARN_REAL_FLOATING_DECL): Likewise. + 2018-08-04 Bruno Haible New module 'posixcheck'. diff --git a/lib/math.in.h b/lib/math.in.h index 053d4e1b85..c30fc202c0 100644 --- a/lib/math.in.h +++ b/lib/math.in.h @@ -92,27 +92,27 @@ _GL_END_NAMESPACE classification macros with an argument of real-floating (that is, one of float, double, or long double). */ #define _GL_WARN_REAL_FLOATING_DECL(func) \ -_GL_MATH_INLINE int \ -rpl_ ## func ## f (float f) \ -{ \ - return func (f); \ -} \ -_GL_MATH_INLINE int \ -rpl_ ## func ## d (double d) \ -{ \ - return func (d); \ -} \ -_GL_MATH_INLINE int \ -rpl_ ## func ## l (long double l) \ -{ \ - return func (l); \ -} \ -_GL_WARN_ON_USE (rpl_ ## func ## f, #func " is unportable - " \ - "use gnulib module " #func " for portability"); \ -_GL_WARN_ON_USE (rpl_ ## func ## d, #func " is unportable - " \ - "use gnulib module " #func " for portability"); \ -_GL_WARN_ON_USE (rpl_ ## func ## l, #func " is unportable - " \ - "use gnulib module " #func " for portability") +_GL_MATH_INLINE int \ +_GL_WARN_ON_USE_ATTRIBUTE (#func " is unportable - " \ + "use gnulib module " #func " for portability") \ +rpl_ ## func ## f (float f) \ +{ \ + return func (f); \ +} \ +_GL_MATH_INLINE int \ +_GL_WARN_ON_USE_ATTRIBUTE (#func " is unportable - " \ + "use gnulib module " #func " for portability") \ +rpl_ ## func ## d (double d) \ +{ \ + return func (d); \ +} \ +_GL_MATH_INLINE int \ +_GL_WARN_ON_USE_ATTRIBUTE (#func " is unportable - " \ + "use gnulib module " #func " for portability") \ +rpl_ ## func ## l (long double l) \ +{ \ + return func (l); \ +} #define _GL_WARN_REAL_FLOATING_IMPL(func, value) \ (sizeof (value) == sizeof (float) ? rpl_ ## func ## f (value) \ : sizeof (value) == sizeof (double) ? rpl_ ## func ## d (value) \ diff --git a/lib/unistd.in.h b/lib/unistd.in.h index 075cab3ee9..8098291ae1 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -432,12 +432,12 @@ extern char **environ; #elif defined GNULIB_POSIXCHECK # if HAVE_RAW_DECL_ENVIRON _GL_UNISTD_INLINE char *** +_GL_WARN_ON_USE_ATTRIBUTE ("environ is unportable - " + "use gnulib module environ for portability") rpl_environ (void) { return &environ; } -_GL_WARN_ON_USE (rpl_environ, "environ is unportable - " - "use gnulib module environ for portability"); # undef environ # define environ (*rpl_environ ()) # endif diff --git a/lib/warn-on-use.h b/lib/warn-on-use.h index 173e2a4b9e..b000dcc2a7 100644 --- a/lib/warn-on-use.h +++ b/lib/warn-on-use.h @@ -20,23 +20,32 @@ supported by the compiler. If the compiler does not support this feature, the macro expands to an unused extern declaration. - This macro is useful for marking a function as a potential + _GL_WARN_ON_USE_ATTRIBUTE ("literal string") expands to the + attribute used in _GL_WARN_ON_USE. If the compiler does not support + this feature, it expands to empty. + + These macros are useful for marking a function as a potential portability trap, with the intent that "literal string" include instructions on the replacement function that should be used - instead. However, one of the reasons that a function is a - portability trap is if it has the wrong signature. Declaring - FUNCTION with a different signature in C is a compilation error, so - this macro must use the same type as any existing declaration so - that programs that avoid the problematic FUNCTION do not fail to - compile merely because they included a header that poisoned the - function. But this implies that _GL_WARN_ON_USE is only safe to - use if FUNCTION is known to already have a declaration. Use of - this macro implies that there must not be any other macro hiding - the declaration of FUNCTION; but undefining FUNCTION first is part - of the poisoning process anyway (although for symbols that are - provided only via a macro, the result is a compilation error rather - than a warning containing "literal string"). Also note that in - C++, it is only safe to use if FUNCTION has no overloads. + instead. + _GL_WARN_ON_USE is for functions with 'extern' linkage. + _GL_WARN_ON_USE_ATTRIBUTE is for functions with 'static' or 'inline' + linkage. + + However, one of the reasons that a function is a portability trap is + if it has the wrong signature. Declaring FUNCTION with a different + signature in C is a compilation error, so this macro must use the + same type as any existing declaration so that programs that avoid + the problematic FUNCTION do not fail to compile merely because they + included a header that poisoned the function. But this implies that + _GL_WARN_ON_USE is only safe to use if FUNCTION is known to already + have a declaration. Use of this macro implies that there must not + be any other macro hiding the declaration of FUNCTION; but + undefining FUNCTION first is part of the poisoning process anyway + (although for symbols that are provided only via a macro, the result + is a compilation error rather than a warning containing + "literal string"). Also note that in C++, it is only safe to use if + FUNCTION has no overloads. For an example, it is possible to poison 'getline' by: - adding a call to gl_WARN_ON_USE_PREPARE([[#include ]], @@ -54,12 +63,21 @@ (less common usage, like &environ, will cause a compilation error rather than issue the nice warning, but the end result of informing the developer about their portability problem is still achieved): - #if HAVE_RAW_DECL_ENVIRON - static char ***rpl_environ (void) { return &environ; } - _GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared"); - # undef environ - # define environ (*rpl_environ ()) - #endif + #if HAVE_RAW_DECL_ENVIRON + static char *** + rpl_environ (void) { return &environ; } + _GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared"); + # undef environ + # define environ (*rpl_environ ()) + #endif + or better (avoiding contradictory use of 'static' and 'extern'): + #if HAVE_RAW_DECL_ENVIRON + static char *** + _GL_WARN_ON_USE_ATTRIBUTE ("environ is not always properly declared") + rpl_environ (void) { return &environ; } + # undef environ + # define environ (*rpl_environ ()) + #endif */ #ifndef _GL_WARN_ON_USE @@ -67,13 +85,17 @@ /* A compiler attribute is available in gcc versions 4.3.0 and later. */ # define _GL_WARN_ON_USE(function, message) \ extern __typeof__ (function) function __attribute__ ((__warning__ (message))) +# define _GL_WARN_ON_USE_ATTRIBUTE(message) \ + __attribute__ ((__warning__ (message))) # elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING /* Verify the existence of the function. */ # define _GL_WARN_ON_USE(function, message) \ extern __typeof__ (function) function +# define _GL_WARN_ON_USE_ATTRIBUTE(message) # else /* Unsupported. */ # define _GL_WARN_ON_USE(function, message) \ _GL_WARN_EXTERN_C int _gl_warn_on_use +# define _GL_WARN_ON_USE_ATTRIBUTE(message) # endif #endif diff --git a/m4/extern-inline.m4 b/m4/extern-inline.m4 index da8a2cc01c..3661cbda5e 100644 --- a/m4/extern-inline.m4 +++ b/m4/extern-inline.m4 @@ -25,7 +25,8 @@ AC_DEFUN([gl_EXTERN_INLINE], if isdigit is mistakenly implemented via a static inline function, a program containing an extern inline function that calls isdigit may not work since the C standard prohibits extern inline functions - from calling static functions. This bug is known to occur on: + from calling static functions (ISO C 99 section 6.7.4.(3). + This bug is known to occur on: OS X 10.8 and earlier; see: https://lists.gnu.org/r/bug-gnulib/2012-12/msg00023.html @@ -38,7 +39,18 @@ AC_DEFUN([gl_EXTERN_INLINE], OS X 10.9 has a macro __header_inline indicating the bug is fixed for C and for clang but remains for g++; see . - Assume DragonFly and FreeBSD will be similar. */ + Assume DragonFly and FreeBSD will be similar. + + GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. It defines a macro + __GNUC_STDC_INLINE__ to indicate this situation or a macro + __GNUC_GNU_INLINE__ to indicate the opposite situation. + GCC 4.2 with -std=c99 or -std=gnu99 implements the GNU C inline + semantics but warns, unless -fgnu89-inline is used: + warning: C99 inline functions are not supported; using GNU89 + warning: to disable this warning use -fgnu89-inline or the gnu_inline function attribute + It defines a macro __GNUC_GNU_INLINE__ to indicate this situation. + */ #if (((defined __APPLE__ && defined __MACH__) \ || defined __DragonFly__ || defined __FreeBSD__) \ && (defined __header_inline \ -- 2.39.5