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