xref: /dflybsd-src/gnu/usr.bin/grep/libgreputils/warn-on-use.h (revision 4ce1b01662e01b4aeb3dbaf5e68504c3aa2a1581)
1*4ce1b016SDaniel Fojt /* A C macro for emitting warnings if a function is used.
2*4ce1b016SDaniel Fojt    Copyright (C) 2010-2020 Free Software Foundation, Inc.
3*4ce1b016SDaniel Fojt 
4*4ce1b016SDaniel Fojt    This program is free software: you can redistribute it and/or modify it
5*4ce1b016SDaniel Fojt    under the terms of the GNU General Public License as published
6*4ce1b016SDaniel Fojt    by the Free Software Foundation; either version 3 of the License, or
7*4ce1b016SDaniel Fojt    (at your option) any later version.
8*4ce1b016SDaniel Fojt 
9*4ce1b016SDaniel Fojt    This program is distributed in the hope that it will be useful,
10*4ce1b016SDaniel Fojt    but WITHOUT ANY WARRANTY; without even the implied warranty of
11*4ce1b016SDaniel Fojt    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12*4ce1b016SDaniel Fojt    General Public License for more details.
13*4ce1b016SDaniel Fojt 
14*4ce1b016SDaniel Fojt    You should have received a copy of the GNU General Public License
15*4ce1b016SDaniel Fojt    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16*4ce1b016SDaniel Fojt 
17*4ce1b016SDaniel Fojt /* _GL_WARN_ON_USE (function, "literal string") issues a declaration
18*4ce1b016SDaniel Fojt    for FUNCTION which will then trigger a compiler warning containing
19*4ce1b016SDaniel Fojt    the text of "literal string" anywhere that function is called, if
20*4ce1b016SDaniel Fojt    supported by the compiler.  If the compiler does not support this
21*4ce1b016SDaniel Fojt    feature, the macro expands to an unused extern declaration.
22*4ce1b016SDaniel Fojt 
23*4ce1b016SDaniel Fojt    _GL_WARN_ON_USE_ATTRIBUTE ("literal string") expands to the
24*4ce1b016SDaniel Fojt    attribute used in _GL_WARN_ON_USE.  If the compiler does not support
25*4ce1b016SDaniel Fojt    this feature, it expands to empty.
26*4ce1b016SDaniel Fojt 
27*4ce1b016SDaniel Fojt    These macros are useful for marking a function as a potential
28*4ce1b016SDaniel Fojt    portability trap, with the intent that "literal string" include
29*4ce1b016SDaniel Fojt    instructions on the replacement function that should be used
30*4ce1b016SDaniel Fojt    instead.
31*4ce1b016SDaniel Fojt    _GL_WARN_ON_USE is for functions with 'extern' linkage.
32*4ce1b016SDaniel Fojt    _GL_WARN_ON_USE_ATTRIBUTE is for functions with 'static' or 'inline'
33*4ce1b016SDaniel Fojt    linkage.
34*4ce1b016SDaniel Fojt 
35*4ce1b016SDaniel Fojt    However, one of the reasons that a function is a portability trap is
36*4ce1b016SDaniel Fojt    if it has the wrong signature.  Declaring FUNCTION with a different
37*4ce1b016SDaniel Fojt    signature in C is a compilation error, so this macro must use the
38*4ce1b016SDaniel Fojt    same type as any existing declaration so that programs that avoid
39*4ce1b016SDaniel Fojt    the problematic FUNCTION do not fail to compile merely because they
40*4ce1b016SDaniel Fojt    included a header that poisoned the function.  But this implies that
41*4ce1b016SDaniel Fojt    _GL_WARN_ON_USE is only safe to use if FUNCTION is known to already
42*4ce1b016SDaniel Fojt    have a declaration.  Use of this macro implies that there must not
43*4ce1b016SDaniel Fojt    be any other macro hiding the declaration of FUNCTION; but
44*4ce1b016SDaniel Fojt    undefining FUNCTION first is part of the poisoning process anyway
45*4ce1b016SDaniel Fojt    (although for symbols that are provided only via a macro, the result
46*4ce1b016SDaniel Fojt    is a compilation error rather than a warning containing
47*4ce1b016SDaniel Fojt    "literal string").  Also note that in C++, it is only safe to use if
48*4ce1b016SDaniel Fojt    FUNCTION has no overloads.
49*4ce1b016SDaniel Fojt 
50*4ce1b016SDaniel Fojt    For an example, it is possible to poison 'getline' by:
51*4ce1b016SDaniel Fojt    - adding a call to gl_WARN_ON_USE_PREPARE([[#include <stdio.h>]],
52*4ce1b016SDaniel Fojt      [getline]) in configure.ac, which potentially defines
53*4ce1b016SDaniel Fojt      HAVE_RAW_DECL_GETLINE
54*4ce1b016SDaniel Fojt    - adding this code to a header that wraps the system <stdio.h>:
55*4ce1b016SDaniel Fojt      #undef getline
56*4ce1b016SDaniel Fojt      #if HAVE_RAW_DECL_GETLINE
57*4ce1b016SDaniel Fojt      _GL_WARN_ON_USE (getline, "getline is required by POSIX 2008, but"
58*4ce1b016SDaniel Fojt        "not universally present; use the gnulib module getline");
59*4ce1b016SDaniel Fojt      #endif
60*4ce1b016SDaniel Fojt 
61*4ce1b016SDaniel Fojt    It is not possible to directly poison global variables.  But it is
62*4ce1b016SDaniel Fojt    possible to write a wrapper accessor function, and poison that
63*4ce1b016SDaniel Fojt    (less common usage, like &environ, will cause a compilation error
64*4ce1b016SDaniel Fojt    rather than issue the nice warning, but the end result of informing
65*4ce1b016SDaniel Fojt    the developer about their portability problem is still achieved):
66*4ce1b016SDaniel Fojt      #if HAVE_RAW_DECL_ENVIRON
67*4ce1b016SDaniel Fojt      static char ***
68*4ce1b016SDaniel Fojt      rpl_environ (void) { return &environ; }
69*4ce1b016SDaniel Fojt      _GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared");
70*4ce1b016SDaniel Fojt      # undef environ
71*4ce1b016SDaniel Fojt      # define environ (*rpl_environ ())
72*4ce1b016SDaniel Fojt      #endif
73*4ce1b016SDaniel Fojt    or better (avoiding contradictory use of 'static' and 'extern'):
74*4ce1b016SDaniel Fojt      #if HAVE_RAW_DECL_ENVIRON
75*4ce1b016SDaniel Fojt      static char ***
76*4ce1b016SDaniel Fojt      _GL_WARN_ON_USE_ATTRIBUTE ("environ is not always properly declared")
77*4ce1b016SDaniel Fojt      rpl_environ (void) { return &environ; }
78*4ce1b016SDaniel Fojt      # undef environ
79*4ce1b016SDaniel Fojt      # define environ (*rpl_environ ())
80*4ce1b016SDaniel Fojt      #endif
81*4ce1b016SDaniel Fojt    */
8256a835a5SJohn Marino #ifndef _GL_WARN_ON_USE
8356a835a5SJohn Marino 
8456a835a5SJohn Marino # if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
8556a835a5SJohn Marino /* A compiler attribute is available in gcc versions 4.3.0 and later.  */
8656a835a5SJohn Marino #  define _GL_WARN_ON_USE(function, message) \
8756a835a5SJohn Marino extern __typeof__ (function) function __attribute__ ((__warning__ (message)))
88*4ce1b016SDaniel Fojt #  define _GL_WARN_ON_USE_ATTRIBUTE(message) \
89*4ce1b016SDaniel Fojt   __attribute__ ((__warning__ (message)))
9056a835a5SJohn Marino # elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
9156a835a5SJohn Marino /* Verify the existence of the function.  */
9256a835a5SJohn Marino #  define _GL_WARN_ON_USE(function, message) \
9356a835a5SJohn Marino extern __typeof__ (function) function
94*4ce1b016SDaniel Fojt #  define _GL_WARN_ON_USE_ATTRIBUTE(message)
9556a835a5SJohn Marino # else /* Unsupported.  */
9656a835a5SJohn Marino #  define _GL_WARN_ON_USE(function, message) \
9756a835a5SJohn Marino _GL_WARN_EXTERN_C int _gl_warn_on_use
98*4ce1b016SDaniel Fojt #  define _GL_WARN_ON_USE_ATTRIBUTE(message)
9956a835a5SJohn Marino # endif
10056a835a5SJohn Marino #endif
10156a835a5SJohn Marino 
10256a835a5SJohn Marino /* _GL_WARN_ON_USE_CXX (function, rettype, parameters_and_attributes, "string")
10356a835a5SJohn Marino    is like _GL_WARN_ON_USE (function, "string"), except that the function is
10456a835a5SJohn Marino    declared with the given prototype, consisting of return type, parameters,
10556a835a5SJohn Marino    and attributes.
10656a835a5SJohn Marino    This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does
10756a835a5SJohn Marino    not work in this case.  */
10856a835a5SJohn Marino #ifndef _GL_WARN_ON_USE_CXX
10956a835a5SJohn Marino # if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
11056a835a5SJohn Marino #  define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
11156a835a5SJohn Marino extern rettype function parameters_and_attributes \
11256a835a5SJohn Marino      __attribute__ ((__warning__ (msg)))
11356a835a5SJohn Marino # elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
11456a835a5SJohn Marino /* Verify the existence of the function.  */
11556a835a5SJohn Marino #  define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
11656a835a5SJohn Marino extern rettype function parameters_and_attributes
11756a835a5SJohn Marino # else /* Unsupported.  */
11856a835a5SJohn Marino #  define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
11956a835a5SJohn Marino _GL_WARN_EXTERN_C int _gl_warn_on_use
12056a835a5SJohn Marino # endif
12156a835a5SJohn Marino #endif
12256a835a5SJohn Marino 
12356a835a5SJohn Marino /* _GL_WARN_EXTERN_C declaration;
12456a835a5SJohn Marino    performs the declaration with C linkage.  */
12556a835a5SJohn Marino #ifndef _GL_WARN_EXTERN_C
12656a835a5SJohn Marino # if defined __cplusplus
12756a835a5SJohn Marino #  define _GL_WARN_EXTERN_C extern "C"
12856a835a5SJohn Marino # else
12956a835a5SJohn Marino #  define _GL_WARN_EXTERN_C extern
13056a835a5SJohn Marino # endif
13156a835a5SJohn Marino #endif
132