xref: /Universal-ctags/gnulib/warn-on-use.h (revision 820c1a8d46849a90376d8eb15b319ac05439f656)
1*820c1a8dSHiroo HAYASHI /* A C macro for emitting warnings if a function is used.
2*820c1a8dSHiroo HAYASHI    Copyright (C) 2010-2021 Free Software Foundation, Inc.
3*820c1a8dSHiroo HAYASHI 
4*820c1a8dSHiroo HAYASHI    This program is free software: you can redistribute it and/or modify it
5*820c1a8dSHiroo HAYASHI    under the terms of the GNU Lesser General Public License as published
6*820c1a8dSHiroo HAYASHI    by the Free Software Foundation; either version 2 of the License, or
7*820c1a8dSHiroo HAYASHI    (at your option) any later version.
8*820c1a8dSHiroo HAYASHI 
9*820c1a8dSHiroo HAYASHI    This program is distributed in the hope that it will be useful,
10*820c1a8dSHiroo HAYASHI    but WITHOUT ANY WARRANTY; without even the implied warranty of
11*820c1a8dSHiroo HAYASHI    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12*820c1a8dSHiroo HAYASHI    Lesser General Public License for more details.
13*820c1a8dSHiroo HAYASHI 
14*820c1a8dSHiroo HAYASHI    You should have received a copy of the GNU Lesser General Public License
15*820c1a8dSHiroo HAYASHI    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16*820c1a8dSHiroo HAYASHI 
17*820c1a8dSHiroo HAYASHI /* _GL_WARN_ON_USE (function, "literal string") issues a declaration
18*820c1a8dSHiroo HAYASHI    for FUNCTION which will then trigger a compiler warning containing
19*820c1a8dSHiroo HAYASHI    the text of "literal string" anywhere that function is called, if
20*820c1a8dSHiroo HAYASHI    supported by the compiler.  If the compiler does not support this
21*820c1a8dSHiroo HAYASHI    feature, the macro expands to an unused extern declaration.
22*820c1a8dSHiroo HAYASHI 
23*820c1a8dSHiroo HAYASHI    _GL_WARN_ON_USE_ATTRIBUTE ("literal string") expands to the
24*820c1a8dSHiroo HAYASHI    attribute used in _GL_WARN_ON_USE.  If the compiler does not support
25*820c1a8dSHiroo HAYASHI    this feature, it expands to empty.
26*820c1a8dSHiroo HAYASHI 
27*820c1a8dSHiroo HAYASHI    These macros are useful for marking a function as a potential
28*820c1a8dSHiroo HAYASHI    portability trap, with the intent that "literal string" include
29*820c1a8dSHiroo HAYASHI    instructions on the replacement function that should be used
30*820c1a8dSHiroo HAYASHI    instead.
31*820c1a8dSHiroo HAYASHI    _GL_WARN_ON_USE is for functions with 'extern' linkage.
32*820c1a8dSHiroo HAYASHI    _GL_WARN_ON_USE_ATTRIBUTE is for functions with 'static' or 'inline'
33*820c1a8dSHiroo HAYASHI    linkage.
34*820c1a8dSHiroo HAYASHI 
35*820c1a8dSHiroo HAYASHI    However, one of the reasons that a function is a portability trap is
36*820c1a8dSHiroo HAYASHI    if it has the wrong signature.  Declaring FUNCTION with a different
37*820c1a8dSHiroo HAYASHI    signature in C is a compilation error, so this macro must use the
38*820c1a8dSHiroo HAYASHI    same type as any existing declaration so that programs that avoid
39*820c1a8dSHiroo HAYASHI    the problematic FUNCTION do not fail to compile merely because they
40*820c1a8dSHiroo HAYASHI    included a header that poisoned the function.  But this implies that
41*820c1a8dSHiroo HAYASHI    _GL_WARN_ON_USE is only safe to use if FUNCTION is known to already
42*820c1a8dSHiroo HAYASHI    have a declaration.  Use of this macro implies that there must not
43*820c1a8dSHiroo HAYASHI    be any other macro hiding the declaration of FUNCTION; but
44*820c1a8dSHiroo HAYASHI    undefining FUNCTION first is part of the poisoning process anyway
45*820c1a8dSHiroo HAYASHI    (although for symbols that are provided only via a macro, the result
46*820c1a8dSHiroo HAYASHI    is a compilation error rather than a warning containing
47*820c1a8dSHiroo HAYASHI    "literal string").  Also note that in C++, it is only safe to use if
48*820c1a8dSHiroo HAYASHI    FUNCTION has no overloads.
49*820c1a8dSHiroo HAYASHI 
50*820c1a8dSHiroo HAYASHI    For an example, it is possible to poison 'getline' by:
51*820c1a8dSHiroo HAYASHI    - adding a call to gl_WARN_ON_USE_PREPARE([[#include <stdio.h>]],
52*820c1a8dSHiroo HAYASHI      [getline]) in configure.ac, which potentially defines
53*820c1a8dSHiroo HAYASHI      HAVE_RAW_DECL_GETLINE
54*820c1a8dSHiroo HAYASHI    - adding this code to a header that wraps the system <stdio.h>:
55*820c1a8dSHiroo HAYASHI      #undef getline
56*820c1a8dSHiroo HAYASHI      #if HAVE_RAW_DECL_GETLINE
57*820c1a8dSHiroo HAYASHI      _GL_WARN_ON_USE (getline, "getline is required by POSIX 2008, but"
58*820c1a8dSHiroo HAYASHI        "not universally present; use the gnulib module getline");
59*820c1a8dSHiroo HAYASHI      #endif
60*820c1a8dSHiroo HAYASHI 
61*820c1a8dSHiroo HAYASHI    It is not possible to directly poison global variables.  But it is
62*820c1a8dSHiroo HAYASHI    possible to write a wrapper accessor function, and poison that
63*820c1a8dSHiroo HAYASHI    (less common usage, like &environ, will cause a compilation error
64*820c1a8dSHiroo HAYASHI    rather than issue the nice warning, but the end result of informing
65*820c1a8dSHiroo HAYASHI    the developer about their portability problem is still achieved):
66*820c1a8dSHiroo HAYASHI      #if HAVE_RAW_DECL_ENVIRON
67*820c1a8dSHiroo HAYASHI      static char ***
68*820c1a8dSHiroo HAYASHI      rpl_environ (void) { return &environ; }
69*820c1a8dSHiroo HAYASHI      _GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared");
70*820c1a8dSHiroo HAYASHI      # undef environ
71*820c1a8dSHiroo HAYASHI      # define environ (*rpl_environ ())
72*820c1a8dSHiroo HAYASHI      #endif
73*820c1a8dSHiroo HAYASHI    or better (avoiding contradictory use of 'static' and 'extern'):
74*820c1a8dSHiroo HAYASHI      #if HAVE_RAW_DECL_ENVIRON
75*820c1a8dSHiroo HAYASHI      static char ***
76*820c1a8dSHiroo HAYASHI      _GL_WARN_ON_USE_ATTRIBUTE ("environ is not always properly declared")
77*820c1a8dSHiroo HAYASHI      rpl_environ (void) { return &environ; }
78*820c1a8dSHiroo HAYASHI      # undef environ
79*820c1a8dSHiroo HAYASHI      # define environ (*rpl_environ ())
80*820c1a8dSHiroo HAYASHI      #endif
81*820c1a8dSHiroo HAYASHI    */
82*820c1a8dSHiroo HAYASHI #ifndef _GL_WARN_ON_USE
83*820c1a8dSHiroo HAYASHI 
84*820c1a8dSHiroo HAYASHI # if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
85*820c1a8dSHiroo HAYASHI /* A compiler attribute is available in gcc versions 4.3.0 and later.  */
86*820c1a8dSHiroo HAYASHI #  define _GL_WARN_ON_USE(function, message) \
87*820c1a8dSHiroo HAYASHI extern __typeof__ (function) function __attribute__ ((__warning__ (message)))
88*820c1a8dSHiroo HAYASHI #  define _GL_WARN_ON_USE_ATTRIBUTE(message) \
89*820c1a8dSHiroo HAYASHI   __attribute__ ((__warning__ (message)))
90*820c1a8dSHiroo HAYASHI # elif __clang_major__ >= 4
91*820c1a8dSHiroo HAYASHI /* Another compiler attribute is available in clang.  */
92*820c1a8dSHiroo HAYASHI #  define _GL_WARN_ON_USE(function, message) \
93*820c1a8dSHiroo HAYASHI extern __typeof__ (function) function \
94*820c1a8dSHiroo HAYASHI   __attribute__ ((__diagnose_if__ (1, message, "warning")))
95*820c1a8dSHiroo HAYASHI #  define _GL_WARN_ON_USE_ATTRIBUTE(message) \
96*820c1a8dSHiroo HAYASHI   __attribute__ ((__diagnose_if__ (1, message, "warning")))
97*820c1a8dSHiroo HAYASHI # elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
98*820c1a8dSHiroo HAYASHI /* Verify the existence of the function.  */
99*820c1a8dSHiroo HAYASHI #  define _GL_WARN_ON_USE(function, message) \
100*820c1a8dSHiroo HAYASHI extern __typeof__ (function) function
101*820c1a8dSHiroo HAYASHI #  define _GL_WARN_ON_USE_ATTRIBUTE(message)
102*820c1a8dSHiroo HAYASHI # else /* Unsupported.  */
103*820c1a8dSHiroo HAYASHI #  define _GL_WARN_ON_USE(function, message) \
104*820c1a8dSHiroo HAYASHI _GL_WARN_EXTERN_C int _gl_warn_on_use
105*820c1a8dSHiroo HAYASHI #  define _GL_WARN_ON_USE_ATTRIBUTE(message)
106*820c1a8dSHiroo HAYASHI # endif
107*820c1a8dSHiroo HAYASHI #endif
108*820c1a8dSHiroo HAYASHI 
109*820c1a8dSHiroo HAYASHI /* _GL_WARN_ON_USE_CXX (function, rettype_gcc, rettype_clang, parameters_and_attributes, "message")
110*820c1a8dSHiroo HAYASHI    is like _GL_WARN_ON_USE (function, "message"), except that in C++ mode the
111*820c1a8dSHiroo HAYASHI    function is declared with the given prototype, consisting of return type,
112*820c1a8dSHiroo HAYASHI    parameters, and attributes.
113*820c1a8dSHiroo HAYASHI    This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does
114*820c1a8dSHiroo HAYASHI    not work in this case.  */
115*820c1a8dSHiroo HAYASHI #ifndef _GL_WARN_ON_USE_CXX
116*820c1a8dSHiroo HAYASHI # if !defined __cplusplus
117*820c1a8dSHiroo HAYASHI #  define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \
118*820c1a8dSHiroo HAYASHI      _GL_WARN_ON_USE (function, msg)
119*820c1a8dSHiroo HAYASHI # else
120*820c1a8dSHiroo HAYASHI #  if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
121*820c1a8dSHiroo HAYASHI /* A compiler attribute is available in gcc versions 4.3.0 and later.  */
122*820c1a8dSHiroo HAYASHI #   define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \
123*820c1a8dSHiroo HAYASHI extern rettype_gcc function parameters_and_attributes \
124*820c1a8dSHiroo HAYASHI   __attribute__ ((__warning__ (msg)))
125*820c1a8dSHiroo HAYASHI #  elif __clang_major__ >= 4
126*820c1a8dSHiroo HAYASHI /* Another compiler attribute is available in clang.  */
127*820c1a8dSHiroo HAYASHI #   define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \
128*820c1a8dSHiroo HAYASHI extern rettype_clang function parameters_and_attributes \
129*820c1a8dSHiroo HAYASHI   __attribute__ ((__diagnose_if__ (1, msg, "warning")))
130*820c1a8dSHiroo HAYASHI #  elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
131*820c1a8dSHiroo HAYASHI /* Verify the existence of the function.  */
132*820c1a8dSHiroo HAYASHI #   define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \
133*820c1a8dSHiroo HAYASHI extern rettype_gcc function parameters_and_attributes
134*820c1a8dSHiroo HAYASHI #  else /* Unsupported.  */
135*820c1a8dSHiroo HAYASHI #   define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \
136*820c1a8dSHiroo HAYASHI _GL_WARN_EXTERN_C int _gl_warn_on_use
137*820c1a8dSHiroo HAYASHI #  endif
138*820c1a8dSHiroo HAYASHI # endif
139*820c1a8dSHiroo HAYASHI #endif
140*820c1a8dSHiroo HAYASHI 
141*820c1a8dSHiroo HAYASHI /* _GL_WARN_EXTERN_C declaration;
142*820c1a8dSHiroo HAYASHI    performs the declaration with C linkage.  */
143*820c1a8dSHiroo HAYASHI #ifndef _GL_WARN_EXTERN_C
144*820c1a8dSHiroo HAYASHI # if defined __cplusplus
145*820c1a8dSHiroo HAYASHI #  define _GL_WARN_EXTERN_C extern "C"
146*820c1a8dSHiroo HAYASHI # else
147*820c1a8dSHiroo HAYASHI #  define _GL_WARN_EXTERN_C extern
148*820c1a8dSHiroo HAYASHI # endif
149*820c1a8dSHiroo HAYASHI #endif
150