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

Reply via email to