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