That is a good point. Thanks for your help/guidance with this. Here's a new patch where I've copied __CRT_INLINE and created a new __MSVC_INLINE which is meant to behave like the origin MSVC inline
From fb39d994898b00ae52106b72f6c835821ae2b455 Mon Sep 17 00:00:00 2001 From: Jonathan Marler <[email protected]> Date: Tue, 13 Jul 2021 00:01:03 -0600 Subject: [PATCH] Define __MSVC_INLINE for inline functions that can be emitted The following example works with MSVC but will fail using the mingw headers: #include <ws2tcpip.h> int main(int argc, char **argv) { return (int)&IN6_IS_ADDR_UNSPECIFIED; } The reason for this is because MinGW is defining this `IN6_IS_ADDR_UNSPECIFIED` function with `extern inline __attribute__((__gnu_inline__))`. A function defined with these attributes will NEVER be emitted. This means you cannot take the address of the function and if the compiler does not inline a call to it, then you'll get a linker error. In the Windows SDK in ws2ipdef.h, this function uses the `__inline` attribute https://docs.microsoft.com/en-us/cpp/cpp/inline-functions-cpp?view=msvc-160 > This keyword tells the compiler that inline expansion is preferred. However, the compiler > can create a separate instance of the function (instantiate) and create standard calling > linkages instead of inserting the code inline. Two cases where this behavior can happen are: > * Recursive Functions > * Functions that are referred to through a pointer elsewhere in the translation unit. Note that this function is not defined in any .lib or .dll file in the Windows sdk and/or runtime, so the only way to be able to take the address of it from the example above is if the compiler is able to emit the function, or if it's defined elsewhere. The problem here appears to be the inclusion of `__attribute__((__gnu_inline__))` which is what tells the compiler NEVER to emit the function definition. Removing this attribute allows the compiler to emit the function which allows its address to be taken, and prevents linker errors if the compiler decides not to inline a call to it. Note that this applies to multiple functions in the ws2 header files. To fix this, I've created a new __MSVC_INLINE that behaves like the MSVC version of inline and redefined the WS2 functions with this inline attribute instead of __CRT_INLINE. Signed-off-by: Jonathan Marler <[email protected]> --- mingw-w64-headers/crt/_mingw.h.in | 13 +++++++++++++ mingw-w64-headers/include/ws2ipdef.h | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mingw-w64-headers/crt/_mingw.h.in b/mingw-w64-headers/crt/_ mingw.h.in index b7fb99f42..2bbd2b611 100644 --- a/mingw-w64-headers/crt/_mingw.h.in +++ b/mingw-w64-headers/crt/_mingw.h.in @@ -93,6 +93,19 @@ limitations in handling dllimport attribute. */ # endif #endif +/*__MSVC_INLINE: like MSVC's inline, compiler may emit the function being defined */ +#ifdef __cplusplus +# define __MSVC_INLINE inline +#elif defined(_MSC_VER) +# define __MSVC_INLINE __inline +#else +# if ((__MINGW_GNUC_PREREQ(4, 3) || defined(__clang__)) && __STDC_VERSION__ >= 199901L) +# define __MSVC_INLINE extern inline +# else +# define __MSVC_INLINE extern __inline__ +# endif +#endif + #if !defined(__MINGW_INTRIN_INLINE) && defined(__GNUC__) #define __MINGW_INTRIN_INLINE extern __inline__ __attribute__((__always_inline__,__gnu_inline__)) #endif diff --git a/mingw-w64-headers/include/ws2ipdef.h b/mingw-w64-headers/include/ws2ipdef.h index d440bbcb8..e45163949 100644 --- a/mingw-w64-headers/include/ws2ipdef.h +++ b/mingw-w64-headers/include/ws2ipdef.h @@ -238,7 +238,7 @@ typedef struct group_source_req { SOCKADDR_STORAGE gsr_source; } GROUP_SOURCE_REQ, *PGROUP_SOURCE_REQ; -#define WS2TCPIP_INLINE __CRT_INLINE +#define WS2TCPIP_INLINE __MSVC_INLINE int IN6_ADDR_EQUAL(const struct in6_addr *,const struct in6_addr *); WS2TCPIP_INLINE int IN6_ADDR_EQUAL(const struct in6_addr *a, const struct in6_addr *b) { -- 2.25.4 On Tue, Jul 13, 2021 at 12:50 AM Martin Storsjö <[email protected]> wrote: > Hi Jonathan, > > On Tue, 13 Jul 2021, Jonathan Marler wrote: > > > The problem here appears to be the inclusion of > > `__attribute__((__gnu_inline__))` which is what > > tells the compiler NEVER to emit the function definition. Removing this > > attribute allows the compiler > > to emit the function which allows its address to be taken, and prevents > > linker errors if the compiler > > decides not to inline a call to it. > > > > Note that this applies to multiple functions in the ws2 header files. > > > > Signed-off-by: Jonathan Marler <[email protected]> > > --- > > mingw-w64-headers/crt/_mingw.h.in | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/mingw-w64-headers/crt/_mingw.h.in b/mingw-w64-headers/crt/_ > > mingw.h.in > > index b7fb99f42..002079910 100644 > > --- a/mingw-w64-headers/crt/_mingw.h.in > > +++ b/mingw-w64-headers/crt/_mingw.h.in > > @@ -87,7 +87,7 @@ limitations in handling dllimport attribute. */ > > # define __CRT_INLINE __inline > > #else > > # if ((__MINGW_GNUC_PREREQ(4, 3) || defined(__clang__)) && > > __STDC_VERSION__ >= 199901L) > > -# define __CRT_INLINE extern inline __attribute__((__gnu_inline__)) > > +# define __CRT_INLINE extern inline > > # else > > # define __CRT_INLINE extern __inline__ > > # endif > > -- > > 2.25.4 > > Your analysis is certainly correct, but I think this particular fix > affects more cases than really needed - __CRT_INLINE is used in lots of > places, and I think many (or at least some) of them are such where an > external definition actually exists, and the behaviour of only taking the > address of the external definition, and inlining only when the compiler > thinks it's worthwhile, is the desired one. > > We've got a couple other defines for inline functions, I think __mingw_ovr > might be one that is for inline functions where there doesn't exist any > non-inline definition elsewhere. So it might be safer (or at least less > disruptive) to just change individual functions, where we've checked that > there's no corresponding external definition, to use that instead of flat > out changing the macro affecting all of them. > > // Martin > > > > _______________________________________________ > Mingw-w64-public mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/mingw-w64-public > _______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
