<div dir="ltr">I think this is basically <a href="https://bugs.llvm.org/show_bug.cgi?id=41018">https://bugs.llvm.org/show_bug.cgi?id=41018</a> , which just needs fixing.<div><br></div><div>Building libc++ with dllexportInlines- might also work (<a href="https://blog.llvm.org/2018/11/30-faster-windows-builds-with-clang-cl_14.html">https://blog.llvm.org/2018/11/30-faster-windows-builds-with-clang-cl_14.html</a>).</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Nov 2, 2020 at 8:26 AM Martin Storsjö via libcxx-dev <<a href="mailto:libcxx-dev@lists.llvm.org">libcxx-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
I'm looking into an issue with how dllimport of classes/methods works when <br>
operating in MSVC mode (i.e. building with clang-cl).<br>
<br>
Methods that aren't supposed to be part of the ABI interface are marked <br>
with _LIBCPP_INLINE_VISIBILITY (expanding to __attribute__ <br>
((__exclude_from_explicit_instantiation__)), or potentially __attribute__ <br>
((__always_inline__))).<br>
<br>
When the whole class is marked dllimport, clang doesn't seem to react to <br>
these attributes at all.<br>
<br>
This is a big practical problem for the method <br>
std::filesystem::path::u8string. The method is marked with <br>
_LIBCPP_INLINE_VISIBILITY, but ends up exported/imported nevertheless.<br>
<br>
In C++17, this method returns a basic_string<char>, while in C++20 it <br>
returns a basic_string<char8_t>. With itanium name mangling, the return <br>
type of a method isn't included in the signature, but with MSVC C++ name <br>
mangling, the two versions of the method are distinctly different.<br>
<br>
So despite the best efforts, a DLL build of the library exports the <br>
function u8string (with whichever return type it had when the lib was <br>
built), and a caller that is built with a different language version will <br>
fail to link as it tries to import the symbol from the DLL.<br>
<br>
A small testcase of the issue looks like this:<br>
<br>
<br>
extern "C" void externFunc(void *ptr);<br>
<br>
class __declspec(dllimport) MyClass {<br>
public:<br>
     void inline<br>
     __attribute__ ((__always_inline__))<br>
     __attribute__ ((__exclude_from_explicit_instantiation__))<br>
     inlineFunc() {<br>
         externFunc(this);<br>
     }<br>
};<br>
<br>
void caller(MyClass *obj) {<br>
    obj->inlineFunc();<br>
}<br>
<br>
<br>
When building an object file out of this, it ends up with an extern call <br>
to __imp_<decoration>inlineFunc. (The rules for dllexport/import are <br>
different in mingw mode, where it ends up behaving as hoped/intended.)<br>
<br>
Is there any way around this, to mark that we really, really, want to <br>
inline any call to this method, despite being in a dllimported class?<br>
<br>
// Martin<br>
<br>
_______________________________________________<br>
libcxx-dev mailing list<br>
<a href="mailto:libcxx-dev@lists.llvm.org" target="_blank">libcxx-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev</a><br>
</blockquote></div>