(+ wine-devel)
On 6/11/22 13:26, LIU Hao wrote:
在 2022-06-12 01:59, Zebediah Figura 写道:
The combination of `extern` with `__gnu_inline__` is necessary to suppress
generation of a function
body if the attached function could not be inlined when compiling as C99.
Why do we need that?
Otherwise there would be errors about multiple definitions.
I don't think there is
anything we can do with these headers. Perhaps WIDL should not generate
`static` for `FORCEINLINE`
functions; or, if that is not an option, `static __inline__` might be a better
alternative.
Is it legal to use 'static __forceinline' or 'extern __forceinline' with MSVC?
If so I imagine we
should find a solution that allows them.
Yes, unfortunately. I don't think there is a solution. `extern inline` and
`inline` are not
equivalent in C.
Right, so, apparently MSVC treats both "inline" and "__forceinline" as
magic bullets—they can both appear with or without 'static' and
'extern'; they'll always generate a function body but can also be
defined in multiple source files (in fact, if the definition differs and
the functions aren't static, an arbitrary one is picked and no warning
is even printed.) And for good measure you can always take the address
too. [So as far as I can tell there's no difference between "inline" and
"extern inline" as far as MSVC is concerned.]
I guess we can't do anything about that without modifying the language.
But of course in lieu of that we should probably fix our headers. I see
at least three options:
(1) Use "FORCEINLINE" instead of "static FORCEINLINE" for these
functions. MSVC never uses FORCEINLINE with static or extern, so this
would be more consistent. The downside is we'd need to provide import
library definitions for all of these functions, though, which seems less
than ideal. (Unless combined with option 3 below.)
(2) Use "static inline" for COM wrappers. This of course drops the
__always_inline__ attribute. I'm inclined to assert that's a non-issue,
but then again I never really saw the point of __always_inline__ anyway.
[I guess it can be used to force the compiler to inline even when
-finline isn't enough, but surely that would never be the case here...]
(2b) Or use "static inline __attribute((__always_inline__))", and define
a new macro to encapsulate that.
(3) Define __forceinline as "static inline" rather than "extern inline".
I have to assume there was a reason this wasn't done in the first place,
but there's no documentation in the file and I couldn't easily find
discussion about it. As far as I can tell this actually matches MSVC
almost exactly, except that multiple definitions will be generated if
something takes the function address. That is arguably a break in
behaviour which is worse than just failing to link, though.
I think my preferred solution is 2 (or 2b I guess). I'm planning to send
the attached patch to winehq (since we need to sync widl from there),
but I'd like to hear some feedback from the mingw-w64 project first.
ἔρρωσθε,
Zeb
From ddd752f7e2d35731da8d27e472505f51ceb46991 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <[email protected]>
Date: Sun, 24 Jul 2022 17:00:10 -0500
Subject: [PATCH] widl: Generate "static inline" instead of "static
FORCEINLINE" for COM inline wrappers.
mingw-w64 defines __forceinline (and therefore FORCEINLINE) as
"extern __inline__ __attribute__((__always_inline__,__gnu_inline__)). This means
that COM inline wrappers specify multiple storage classes and hence cannot be
compiled.
Wine defines FORCEINLINE simply as "inline" (and uses "static" everywhere), so
this is a non-issue for Wine. However, since Wine and mingw-w64 share the source
code of widl and of most IDL headers, this patch changes the definition for both
projects.
There's no reason to force inlining here, especially since the wrappers need to
be manually enabled, and we don't need to match PSDK semantics where these
wrappers don't even exist.
Signed-off-by: Zebediah Figura <[email protected]>
---
tools/widl/header.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 8b9c64e1e38..0c60e266949 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -1315,7 +1315,7 @@ static void write_inline_wrappers(FILE *header, const type_t *iface, const type_
if (!is_callas(func->attrs)) {
const var_t *arg;
- fprintf(header, "static FORCEINLINE ");
+ fprintf(header, "static inline ");
write_type_decl_left(header, type_function_get_ret(func->declspec.type));
fprintf(header, " %s_%s(", name, get_name(func));
write_args(header, type_function_get_args(func->declspec.type), name, 1, FALSE, NAME_C);
--
2.35.1
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public