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