warn-on-use.h 5.99 KB
Newer Older
Paul Eggert's avatar
Paul Eggert committed
1
/* A C macro for emitting warnings if a function is used.
Paul Eggert's avatar
Paul Eggert committed
2
   Copyright (C) 2010-2020 Free Software Foundation, Inc.
Paul Eggert's avatar
Paul Eggert committed
3 4 5 6 7 8 9 10 11

   This program is free software: you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published
   by the Free Software Foundation; either version 3 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
12
   General Public License for more details.
Paul Eggert's avatar
Paul Eggert committed
13 14

   You should have received a copy of the GNU General Public License
Paul Eggert's avatar
Paul Eggert committed
15
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
Paul Eggert's avatar
Paul Eggert committed
16 17 18 19 20 21 22

/* _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.

Paul Eggert's avatar
Paul Eggert committed
23 24 25 26 27
   _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
Paul Eggert's avatar
Paul Eggert committed
28 29
   portability trap, with the intent that "literal string" include
   instructions on the replacement function that should be used
Paul Eggert's avatar
Paul Eggert committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
   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.
Paul Eggert's avatar
Paul Eggert committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

   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):
Paul Eggert's avatar
Paul Eggert committed
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
     #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
Paul Eggert's avatar
Paul Eggert committed
81 82 83 84 85 86 87
   */
#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)))
Paul Eggert's avatar
Paul Eggert committed
88 89
#  define _GL_WARN_ON_USE_ATTRIBUTE(message) \
  __attribute__ ((__warning__ (message)))
Paul Eggert's avatar
Paul Eggert committed
90 91 92 93
# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
/* Verify the existence of the function.  */
#  define _GL_WARN_ON_USE(function, message) \
extern __typeof__ (function) function
Paul Eggert's avatar
Paul Eggert committed
94
#  define _GL_WARN_ON_USE_ATTRIBUTE(message)
Paul Eggert's avatar
Paul Eggert committed
95 96 97
# else /* Unsupported.  */
#  define _GL_WARN_ON_USE(function, message) \
_GL_WARN_EXTERN_C int _gl_warn_on_use
Paul Eggert's avatar
Paul Eggert committed
98
#  define _GL_WARN_ON_USE_ATTRIBUTE(message)
Paul Eggert's avatar
Paul Eggert committed
99 100 101 102
# endif
#endif

/* _GL_WARN_ON_USE_CXX (function, rettype, parameters_and_attributes, "string")
Paul Eggert's avatar
Paul Eggert committed
103 104 105
   is like _GL_WARN_ON_USE (function, "string"), except that in C++ mode the
   function is declared with the given prototype, consisting of return type,
   parameters, and attributes.
Paul Eggert's avatar
Paul Eggert committed
106 107 108
   This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does
   not work in this case.  */
#ifndef _GL_WARN_ON_USE_CXX
Paul Eggert's avatar
Paul Eggert committed
109
# if !defined __cplusplus
Paul Eggert's avatar
Paul Eggert committed
110
#  define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
Paul Eggert's avatar
Paul Eggert committed
111 112 113 114
     _GL_WARN_ON_USE (function, msg)
# else
#  if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
#   define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
Paul Eggert's avatar
Paul Eggert committed
115 116
extern rettype function parameters_and_attributes \
     __attribute__ ((__warning__ (msg)))
Paul Eggert's avatar
Paul Eggert committed
117
#  elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
Paul Eggert's avatar
Paul Eggert committed
118
/* Verify the existence of the function.  */
Paul Eggert's avatar
Paul Eggert committed
119
#   define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
Paul Eggert's avatar
Paul Eggert committed
120
extern rettype function parameters_and_attributes
Paul Eggert's avatar
Paul Eggert committed
121 122
#  else /* Unsupported.  */
#   define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
Paul Eggert's avatar
Paul Eggert committed
123
_GL_WARN_EXTERN_C int _gl_warn_on_use
Paul Eggert's avatar
Paul Eggert committed
124
#  endif
Paul Eggert's avatar
Paul Eggert committed
125 126 127 128 129 130 131 132 133 134 135 136
# endif
#endif

/* _GL_WARN_EXTERN_C declaration;
   performs the declaration with C linkage.  */
#ifndef _GL_WARN_EXTERN_C
# if defined __cplusplus
#  define _GL_WARN_EXTERN_C extern "C"
# else
#  define _GL_WARN_EXTERN_C extern
# endif
#endif