1 /* C++ compatible function declaration macros. 2 Copyright (C) 2010-2021 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 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_MDA (func, rettype, parameters); 150 is to be used when func is a Microsoft deprecated alias, on native Windows. 151 It declares a C++ alias called GNULIB_NAMESPACE::func 152 that redirects to _func, if GNULIB_NAMESPACE is defined. 153 Example: 154 _GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...)); 155 */ 156 #define _GL_CXXALIAS_MDA(func,rettype,parameters) \ 157 _GL_CXXALIAS_RPL_1 (func, _##func, rettype, parameters) 158 159 /* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters); 160 is like _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters); 161 except that the C function rpl_func may have a slightly different 162 declaration. A cast is used to silence the "invalid conversion" error 163 that would otherwise occur. */ 164 #if defined __cplusplus && defined GNULIB_NAMESPACE 165 # define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ 166 namespace GNULIB_NAMESPACE \ 167 { \ 168 static const struct _gl_ ## func ## _wrapper \ 169 { \ 170 typedef rettype (*type) parameters; \ 171 \ 172 inline operator type () const \ 173 { \ 174 return reinterpret_cast<type>(::rpl_func); \ 175 } \ 176 } func = {}; \ 177 } \ 178 _GL_EXTERN_C int _gl_cxxalias_dummy 179 #else 180 # define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ 181 _GL_EXTERN_C int _gl_cxxalias_dummy 182 #endif 183 184 /* _GL_CXXALIAS_MDA_CAST (func, rettype, parameters); 185 is like _GL_CXXALIAS_MDA (func, rettype, parameters); 186 except that the C function func may have a slightly different declaration. 187 A cast is used to silence the "invalid conversion" error that would 188 otherwise occur. */ 189 #define _GL_CXXALIAS_MDA_CAST(func,rettype,parameters) \ 190 _GL_CXXALIAS_RPL_CAST_1 (func, _##func, rettype, parameters) 191 192 /* _GL_CXXALIAS_SYS (func, rettype, parameters); 193 declares a C++ alias called GNULIB_NAMESPACE::func 194 that redirects to the system provided function func, if GNULIB_NAMESPACE 195 is defined. 196 Example: 197 _GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); 198 199 Wrapping func in an object with an inline conversion operator 200 avoids a reference to func unless GNULIB_NAMESPACE::func is 201 actually used in the program. */ 202 #if defined __cplusplus && defined GNULIB_NAMESPACE 203 # define _GL_CXXALIAS_SYS(func,rettype,parameters) \ 204 namespace GNULIB_NAMESPACE \ 205 { \ 206 static const struct _gl_ ## func ## _wrapper \ 207 { \ 208 typedef rettype (*type) parameters; \ 209 \ 210 inline operator type () const \ 211 { \ 212 return ::func; \ 213 } \ 214 } func = {}; \ 215 } \ 216 _GL_EXTERN_C int _gl_cxxalias_dummy 217 #else 218 # define _GL_CXXALIAS_SYS(func,rettype,parameters) \ 219 _GL_EXTERN_C int _gl_cxxalias_dummy 220 #endif 221 222 /* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters); 223 is like _GL_CXXALIAS_SYS (func, rettype, parameters); 224 except that the C function func may have a slightly different declaration. 225 A cast is used to silence the "invalid conversion" error that would 226 otherwise occur. */ 227 #if defined __cplusplus && defined GNULIB_NAMESPACE 228 # define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ 229 namespace GNULIB_NAMESPACE \ 230 { \ 231 static const struct _gl_ ## func ## _wrapper \ 232 { \ 233 typedef rettype (*type) parameters; \ 234 \ 235 inline operator type () const \ 236 { \ 237 return reinterpret_cast<type>(::func); \ 238 } \ 239 } func = {}; \ 240 } \ 241 _GL_EXTERN_C int _gl_cxxalias_dummy 242 #else 243 # define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ 244 _GL_EXTERN_C int _gl_cxxalias_dummy 245 #endif 246 247 /* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2); 248 is like _GL_CXXALIAS_SYS (func, rettype, parameters); 249 except that the C function is picked among a set of overloaded functions, 250 namely the one with rettype2 and parameters2. Two consecutive casts 251 are used to silence the "cannot find a match" and "invalid conversion" 252 errors that would otherwise occur. */ 253 #if defined __cplusplus && defined GNULIB_NAMESPACE 254 /* The outer cast must be a reinterpret_cast. 255 The inner cast: When the function is defined as a set of overloaded 256 functions, it works as a static_cast<>, choosing the designated variant. 257 When the function is defined as a single variant, it works as a 258 reinterpret_cast<>. The parenthesized cast syntax works both ways. */ 259 # define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ 260 namespace GNULIB_NAMESPACE \ 261 { \ 262 static const struct _gl_ ## func ## _wrapper \ 263 { \ 264 typedef rettype (*type) parameters; \ 265 \ 266 inline operator type () const \ 267 { \ 268 return reinterpret_cast<type>((rettype2 (*) parameters2)(::func)); \ 269 } \ 270 } func = {}; \ 271 } \ 272 _GL_EXTERN_C int _gl_cxxalias_dummy 273 #else 274 # define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ 275 _GL_EXTERN_C int _gl_cxxalias_dummy 276 #endif 277 278 /* _GL_CXXALIASWARN (func); 279 causes a warning to be emitted when ::func is used but not when 280 GNULIB_NAMESPACE::func is used. func must be defined without overloaded 281 variants. */ 282 #if defined __cplusplus && defined GNULIB_NAMESPACE 283 # define _GL_CXXALIASWARN(func) \ 284 _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE) 285 # define _GL_CXXALIASWARN_1(func,namespace) \ 286 _GL_CXXALIASWARN_2 (func, namespace) 287 /* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>, 288 we enable the warning only when not optimizing. */ 289 # if !(defined __GNUC__ && !defined __clang__ && __OPTIMIZE__) 290 # define _GL_CXXALIASWARN_2(func,namespace) \ 291 _GL_WARN_ON_USE (func, \ 292 "The symbol ::" #func " refers to the system function. " \ 293 "Use " #namespace "::" #func " instead.") 294 # elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING 295 # define _GL_CXXALIASWARN_2(func,namespace) \ 296 extern __typeof__ (func) func 297 # else 298 # define _GL_CXXALIASWARN_2(func,namespace) \ 299 _GL_EXTERN_C int _gl_cxxalias_dummy 300 # endif 301 #else 302 # define _GL_CXXALIASWARN(func) \ 303 _GL_EXTERN_C int _gl_cxxalias_dummy 304 #endif 305 306 /* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes); 307 causes a warning to be emitted when the given overloaded variant of ::func 308 is used but not when GNULIB_NAMESPACE::func is used. */ 309 #if defined __cplusplus && defined GNULIB_NAMESPACE 310 # define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ 311 _GL_CXXALIASWARN1_1 (func, rettype, parameters_and_attributes, \ 312 GNULIB_NAMESPACE) 313 # define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \ 314 _GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace) 315 /* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>, 316 we enable the warning only when not optimizing. */ 317 # if !(defined __GNUC__ && !defined __clang__ && __OPTIMIZE__) 318 # define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ 319 _GL_WARN_ON_USE_CXX (func, rettype, rettype, parameters_and_attributes, \ 320 "The symbol ::" #func " refers to the system function. " \ 321 "Use " #namespace "::" #func " instead.") 322 # else 323 # define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ 324 _GL_EXTERN_C int _gl_cxxalias_dummy 325 # endif 326 #else 327 # define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ 328 _GL_EXTERN_C int _gl_cxxalias_dummy 329 #endif 330 331 #endif /* _GL_CXXDEFS_H */ 332