1 /* C++ compatible function declaration macros. 2 Copyright (C) 2010-2019 Free Software Foundation, Inc. 3 4 This program is free software: you can redistribute it and/or modify it 5 under the terms of the GNU Lesser General Public License as published 6 by the Free Software Foundation; either version 2.1 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public License 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 16 17 #ifndef _GL_CXXDEFS_H 18 #define _GL_CXXDEFS_H 19 20 /* Begin/end the GNULIB_NAMESPACE namespace. */ 21 #if defined __cplusplus && defined GNULIB_NAMESPACE 22 # define _GL_BEGIN_NAMESPACE namespace GNULIB_NAMESPACE { 23 # define _GL_END_NAMESPACE } 24 #else 25 # define _GL_BEGIN_NAMESPACE 26 # define _GL_END_NAMESPACE 27 #endif 28 29 /* The three most frequent use cases of these macros are: 30 31 * For providing a substitute for a function that is missing on some 32 platforms, but is declared and works fine on the platforms on which 33 it exists: 34 35 #if @GNULIB_FOO@ 36 # if !@HAVE_FOO@ 37 _GL_FUNCDECL_SYS (foo, ...); 38 # endif 39 _GL_CXXALIAS_SYS (foo, ...); 40 _GL_CXXALIASWARN (foo); 41 #elif defined GNULIB_POSIXCHECK 42 ... 43 #endif 44 45 * For providing a replacement for a function that exists on all platforms, 46 but is broken/insufficient and needs to be replaced on some platforms: 47 48 #if @GNULIB_FOO@ 49 # if @REPLACE_FOO@ 50 # if !(defined __cplusplus && defined GNULIB_NAMESPACE) 51 # undef foo 52 # define foo rpl_foo 53 # endif 54 _GL_FUNCDECL_RPL (foo, ...); 55 _GL_CXXALIAS_RPL (foo, ...); 56 # else 57 _GL_CXXALIAS_SYS (foo, ...); 58 # endif 59 _GL_CXXALIASWARN (foo); 60 #elif defined GNULIB_POSIXCHECK 61 ... 62 #endif 63 64 * For providing a replacement for a function that exists on some platforms 65 but is broken/insufficient and needs to be replaced on some of them and 66 is additionally either missing or undeclared on some other platforms: 67 68 #if @GNULIB_FOO@ 69 # if @REPLACE_FOO@ 70 # if !(defined __cplusplus && defined GNULIB_NAMESPACE) 71 # undef foo 72 # define foo rpl_foo 73 # endif 74 _GL_FUNCDECL_RPL (foo, ...); 75 _GL_CXXALIAS_RPL (foo, ...); 76 # else 77 # if !@HAVE_FOO@ or if !@HAVE_DECL_FOO@ 78 _GL_FUNCDECL_SYS (foo, ...); 79 # endif 80 _GL_CXXALIAS_SYS (foo, ...); 81 # endif 82 _GL_CXXALIASWARN (foo); 83 #elif defined GNULIB_POSIXCHECK 84 ... 85 #endif 86 */ 87 88 /* _GL_EXTERN_C declaration; 89 performs the declaration with C linkage. */ 90 #if defined __cplusplus 91 # define _GL_EXTERN_C extern "C" 92 #else 93 # define _GL_EXTERN_C extern 94 #endif 95 96 /* _GL_FUNCDECL_RPL (func, rettype, parameters_and_attributes); 97 declares a replacement function, named rpl_func, with the given prototype, 98 consisting of return type, parameters, and attributes. 99 Example: 100 _GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...) 101 _GL_ARG_NONNULL ((1))); 102 */ 103 #define _GL_FUNCDECL_RPL(func,rettype,parameters_and_attributes) \ 104 _GL_FUNCDECL_RPL_1 (rpl_##func, rettype, parameters_and_attributes) 105 #define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters_and_attributes) \ 106 _GL_EXTERN_C rettype rpl_func parameters_and_attributes 107 108 /* _GL_FUNCDECL_SYS (func, rettype, parameters_and_attributes); 109 declares the system function, named func, with the given prototype, 110 consisting of return type, parameters, and attributes. 111 Example: 112 _GL_FUNCDECL_SYS (open, int, (const char *filename, int flags, ...) 113 _GL_ARG_NONNULL ((1))); 114 */ 115 #define _GL_FUNCDECL_SYS(func,rettype,parameters_and_attributes) \ 116 _GL_EXTERN_C rettype func parameters_and_attributes 117 118 /* _GL_CXXALIAS_RPL (func, rettype, parameters); 119 declares a C++ alias called GNULIB_NAMESPACE::func 120 that redirects to rpl_func, if GNULIB_NAMESPACE is defined. 121 Example: 122 _GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...)); 123 124 Wrapping rpl_func in an object with an inline conversion operator 125 avoids a reference to rpl_func unless GNULIB_NAMESPACE::func is 126 actually used in the program. */ 127 #define _GL_CXXALIAS_RPL(func,rettype,parameters) \ 128 _GL_CXXALIAS_RPL_1 (func, rpl_##func, rettype, parameters) 129 #if defined __cplusplus && defined GNULIB_NAMESPACE 130 # define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ 131 namespace GNULIB_NAMESPACE \ 132 { \ 133 static const struct _gl_ ## func ## _wrapper \ 134 { \ 135 typedef rettype (*type) parameters; \ 136 \ 137 inline operator type () const \ 138 { \ 139 return ::rpl_func; \ 140 } \ 141 } func = {}; \ 142 } \ 143 _GL_EXTERN_C int _gl_cxxalias_dummy 144 #else 145 # define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ 146 _GL_EXTERN_C int _gl_cxxalias_dummy 147 #endif 148 149 /* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters); 150 is like _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters); 151 except that the C function rpl_func may have a slightly different 152 declaration. A cast is used to silence the "invalid conversion" error 153 that would otherwise occur. */ 154 #if defined __cplusplus && defined GNULIB_NAMESPACE 155 # define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ 156 namespace GNULIB_NAMESPACE \ 157 { \ 158 static const struct _gl_ ## func ## _wrapper \ 159 { \ 160 typedef rettype (*type) parameters; \ 161 \ 162 inline operator type () const \ 163 { \ 164 return reinterpret_cast<type>(::rpl_func); \ 165 } \ 166 } func = {}; \ 167 } \ 168 _GL_EXTERN_C int _gl_cxxalias_dummy 169 #else 170 # define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ 171 _GL_EXTERN_C int _gl_cxxalias_dummy 172 #endif 173 174 /* _GL_CXXALIAS_SYS (func, rettype, parameters); 175 declares a C++ alias called GNULIB_NAMESPACE::func 176 that redirects to the system provided function func, if GNULIB_NAMESPACE 177 is defined. 178 Example: 179 _GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); 180 181 Wrapping func in an object with an inline conversion operator 182 avoids a reference to func unless GNULIB_NAMESPACE::func is 183 actually used in the program. */ 184 #if defined __cplusplus && defined GNULIB_NAMESPACE 185 # define _GL_CXXALIAS_SYS(func,rettype,parameters) \ 186 namespace GNULIB_NAMESPACE \ 187 { \ 188 static const struct _gl_ ## func ## _wrapper \ 189 { \ 190 typedef rettype (*type) parameters; \ 191 \ 192 inline operator type () const \ 193 { \ 194 return ::func; \ 195 } \ 196 } func = {}; \ 197 } \ 198 _GL_EXTERN_C int _gl_cxxalias_dummy 199 #else 200 # define _GL_CXXALIAS_SYS(func,rettype,parameters) \ 201 _GL_EXTERN_C int _gl_cxxalias_dummy 202 #endif 203 204 /* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters); 205 is like _GL_CXXALIAS_SYS (func, rettype, parameters); 206 except that the C function func may have a slightly different declaration. 207 A cast is used to silence the "invalid conversion" error that would 208 otherwise occur. */ 209 #if defined __cplusplus && defined GNULIB_NAMESPACE 210 # define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ 211 namespace GNULIB_NAMESPACE \ 212 { \ 213 static const struct _gl_ ## func ## _wrapper \ 214 { \ 215 typedef rettype (*type) parameters; \ 216 \ 217 inline operator type () const \ 218 { \ 219 return reinterpret_cast<type>(::func); \ 220 } \ 221 } func = {}; \ 222 } \ 223 _GL_EXTERN_C int _gl_cxxalias_dummy 224 #else 225 # define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ 226 _GL_EXTERN_C int _gl_cxxalias_dummy 227 #endif 228 229 /* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2); 230 is like _GL_CXXALIAS_SYS (func, rettype, parameters); 231 except that the C function is picked among a set of overloaded functions, 232 namely the one with rettype2 and parameters2. Two consecutive casts 233 are used to silence the "cannot find a match" and "invalid conversion" 234 errors that would otherwise occur. */ 235 #if defined __cplusplus && defined GNULIB_NAMESPACE 236 /* The outer cast must be a reinterpret_cast. 237 The inner cast: When the function is defined as a set of overloaded 238 functions, it works as a static_cast<>, choosing the designated variant. 239 When the function is defined as a single variant, it works as a 240 reinterpret_cast<>. The parenthesized cast syntax works both ways. */ 241 # define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ 242 namespace GNULIB_NAMESPACE \ 243 { \ 244 static const struct _gl_ ## func ## _wrapper \ 245 { \ 246 typedef rettype (*type) parameters; \ 247 \ 248 inline operator type () const \ 249 { \ 250 return reinterpret_cast<type>((rettype2 (*) parameters2)(::func)); \ 251 } \ 252 } func = {}; \ 253 } \ 254 _GL_EXTERN_C int _gl_cxxalias_dummy 255 #else 256 # define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ 257 _GL_EXTERN_C int _gl_cxxalias_dummy 258 #endif 259 260 /* _GL_CXXALIASWARN (func); 261 causes a warning to be emitted when ::func is used but not when 262 GNULIB_NAMESPACE::func is used. func must be defined without overloaded 263 variants. */ 264 #if defined __cplusplus && defined GNULIB_NAMESPACE 265 # define _GL_CXXALIASWARN(func) \ 266 _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE) 267 # define _GL_CXXALIASWARN_1(func,namespace) \ 268 _GL_CXXALIASWARN_2 (func, namespace) 269 /* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>, 270 we enable the warning only when not optimizing. */ 271 # if !__OPTIMIZE__ 272 # define _GL_CXXALIASWARN_2(func,namespace) \ 273 _GL_WARN_ON_USE (func, \ 274 "The symbol ::" #func " refers to the system function. " \ 275 "Use " #namespace "::" #func " instead.") 276 # elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING 277 # define _GL_CXXALIASWARN_2(func,namespace) \ 278 extern __typeof__ (func) func 279 # else 280 # define _GL_CXXALIASWARN_2(func,namespace) \ 281 _GL_EXTERN_C int _gl_cxxalias_dummy 282 # endif 283 #else 284 # define _GL_CXXALIASWARN(func) \ 285 _GL_EXTERN_C int _gl_cxxalias_dummy 286 #endif 287 288 /* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes); 289 causes a warning to be emitted when the given overloaded variant of ::func 290 is used but not when GNULIB_NAMESPACE::func is used. */ 291 #if defined __cplusplus && defined GNULIB_NAMESPACE 292 # define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ 293 _GL_CXXALIASWARN1_1 (func, rettype, parameters_and_attributes, \ 294 GNULIB_NAMESPACE) 295 # define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \ 296 _GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace) 297 /* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>, 298 we enable the warning only when not optimizing. */ 299 # if !__OPTIMIZE__ 300 # define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ 301 _GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \ 302 "The symbol ::" #func " refers to the system function. " \ 303 "Use " #namespace "::" #func " instead.") 304 # elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING 305 # define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ 306 extern __typeof__ (func) func 307 # else 308 # define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ 309 _GL_EXTERN_C int _gl_cxxalias_dummy 310 # endif 311 #else 312 # define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ 313 _GL_EXTERN_C int _gl_cxxalias_dummy 314 #endif 315 316 #endif /* _GL_CXXDEFS_H */ 317