changeset 12723:72890f398afa

warn-on-use: new module The goal of GNULIB_POSIXCHECK is to allow a developer on a reasonably portable system to detect instances where they may have succeeded because their system is up-to-date, but where compilation would fail or create a misbehaving application on some other system due to some portability problem, all without requiring that the developer have access to other machines. In other words, we want to poison all interfaces that have a gnulib replacement if the corresponding gnulib module is not in use. For macros, the solution is undefining the macro; unfortunately this causes compilation error without many details as to why, but it is better than nothing. For functions, the solution is to cause a warning if the function is used. Previously, the link-warning could poison functions, but only on glibc systems and with gcc. This module introduces _GL_WARN_ON_USE as a way of poisoning functions for a few more systems. Using the gcc __warning__ attribute (added in 4.3.0, early 2008) rather than using link-warning.h is favorable because: 1) Provides a warning immediately at compile-time. The user does not have to wait until he links a program. 2) Less use of C macros. Less risk of collision. 3) It's available on more platforms. Depends only on GCC. 4) The formatting of the message is nicer. There is a minor regression: the gcc attribute is currently not as powerful as a link warning at detecting uses via function pointers: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42384 However, that style of coding is less frequent. * modules/warn-on-use: New file. * build-aux/warn-on-use.h: Likewise. * m4/warn-on-use.m4: Likewise. * MODULES.html.sh (Support for building): Mention it. Signed-off-by: Eric Blake <ebb9@byu.net>
author Eric Blake <ebb9@byu.net>
date Wed, 16 Dec 2009 14:53:06 -0700
parents 6f44ad9f6514
children bc2866336bbb
files ChangeLog MODULES.html.sh build-aux/warn-on-use.h m4/warn-on-use.m4 modules/warn-on-use
diffstat 5 files changed, 166 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2010-01-11  Eric Blake  <ebb9@byu.net>
+
+	warn-on-use: new module
+	* modules/warn-on-use: New file.
+	* build-aux/warn-on-use.h: Likewise.
+	* m4/warn-on-use.m4: Likewise.
+	* MODULES.html.sh (Support for building): Mention it.
+
 2010-01-10  Bruno Haible  <bruno@clisp.org>
 
 	Tests for module 'unistr/u32-strdup'.
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -3172,6 +3172,7 @@
 
   func_begin_table
   func_module absolute-header
+  func_module arg-nonnull
   func_module config-h
   func_module configmake
   func_module dummy
@@ -3184,14 +3185,15 @@
   func_module lib-msvc-compat
   func_module lib-symbol-versions
   func_module link-warning
+  func_module manywarnings
   func_module no-c++
   func_module relocatable-lib
   func_module relocatable-lib-lgpl
   func_module relocatable-prog
   func_module relocatable-prog-wrapper
   func_module relocatable-script
+  func_module warn-on-use
   func_module warnings
-  func_module manywarnings
   func_end_table
 
   element="Support for building documentation"
new file mode 100644
--- /dev/null
+++ b/build-aux/warn-on-use.h
@@ -0,0 +1,75 @@
+/* A C macro for emitting warnings if a function is used.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   This program 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 of the License, or
+   (at your option) any later version.
+
+   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* _GL_WARN_ON_USE(function, "literal string") issues a declaration
+   for FUNCTION which will then trigger a compiler warning containing
+   the text of "literal string" anywhere that function is called, if
+   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
+   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.
+
+   For an example, it is possible to poison 'getline' by:
+   - adding a call to gl_WARN_ON_USE_PREPARE([[#include <stdio.h>]],
+     [getline]) in configure.ac, which potentially defines
+     HAVE_RAW_DECL_GETLINE
+   - adding this code to a header that wraps the system <stdio.h>:
+     #undef getline
+     #if HAVE_RAW_DECL_GETLINE
+     _GL_WARN_ON_USE (getline, "getline is required by POSIX 2008, but"
+       "not universally present; use the gnulib module getline");
+     #endif
+
+   It is not possible to directly poison global variables.  But it is
+   possible to write a wrapper accessor function, and poison that
+   (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 inline 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
+   */
+#ifndef _GL_WARN_ON_USE
+
+# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
+/* 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)))
+
+# else /* Unsupported.  */
+#  define _GL_WARN_ON_USE(function, message) \
+extern int _gl_warn_on_use
+# endif
+#endif
new file mode 100644
--- /dev/null
+++ b/m4/warn-on-use.m4
@@ -0,0 +1,45 @@
+# warn-on-use.m4 serial 1
+dnl Copyright (C) 2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# gl_WARN_ON_USE_PREPARE(INCLUDES, NAMES)
+# ---------------------------------------
+# For each whitespace-separated element in the list of NAMES, define
+# HAVE_RAW_DECL_name if the function has a declaration among INCLUDES
+# even after being undefined as a macro.
+#
+# See warn-on-use.h for some hints on how to poison function names, as
+# well as ideas on poisoning global variables and macros.  NAMES may
+# include global variables, but remember that only functions work with
+# _GL_WARN_ON_USE.  Typically, INCLUDES only needs to list a single
+# header, but if the replacement header pulls in other headers because
+# some systems declare functions in the wrong header, then INCLUDES
+# should do likewise.
+#
+# If you assume C89, then it is generally safe to assume declarations
+# for functions declared in that standard (such as gets) without
+# needing gl_WARN_ON_USE_PREPARE.
+AC_DEFUN([gl_WARN_ON_USE_PREPARE],
+[
+  m4_foreach_w([gl_decl], [$2],
+    [AH_TEMPLATE([HAVE_RAW_DECL_]AS_TR_CPP(m4_defn([gl_decl])),
+      [Define to 1 if ]m4_defn([gl_decl])[ is declared even after
+       undefining macros.])])dnl
+  for gl_func in m4_flatten([$2]); do
+    AS_VAR_PUSHDEF([gl_Symbol], [gl_cv_have_raw_decl_$gl_func])dnl
+    AC_CACHE_CHECK([whether $gl_func is declared without a macro],
+      [gl_Symbol],
+      [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$1],
+[@%:@undef $gl_func
+  (void) $gl_func;])],
+        [AS_VAR_SET([gl_Symbol], [yes])], [AS_VAR_SET([gl_Symbol], [no])])])
+     AS_VAR_IF([gl_Symbol], [yes],
+       [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_RAW_DECL_$gl_func]), [1])
+       dnl shortcut - if the raw declaration exists, then set a cache
+       dnl variable to allow skipping any later AC_CHECK_DECL efforts
+       eval ac_cv_have_decl_$gl_func=yes])
+    AS_VAR_POPDEF([gl_Symbol])dnl
+  done
+])
new file mode 100644
--- /dev/null
+++ b/modules/warn-on-use
@@ -0,0 +1,35 @@
+Description:
+A C macro for emitting a warning if a function is used.
+
+Applicability:
+all
+
+Files:
+build-aux/warn-on-use.h
+m4/warn-on-use.m4
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+BUILT_SOURCES += warn-on-use.h
+# The warn-on-use.h that gets inserted into generated .h files is the same as
+# build-aux/warn-on-use.h, except that it has the copyright header cut off.
+warn-on-use.h: $(top_srcdir)/build-aux/warn-on-use.h
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	sed -n -e '/^.ifndef/,$$p' \
+	  < $(top_srcdir)/build-aux/warn-on-use.h \
+	  > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += warn-on-use.h warn-on-use.h-t
+
+WARN_ON_USE_H=warn-on-use.h
+
+Include:
+
+License:
+LGPLv2+
+
+Maintainer:
+Eric Blake