dllimport vs inline methods in MSVC mode/clang-cl

Hi,

I'm looking into an issue with how dllimport of classes/methods works when operating in MSVC mode (i.e. building with clang-cl).

Methods that aren't supposed to be part of the ABI interface are marked with _LIBCPP_INLINE_VISIBILITY (expanding to __attribute__ ((__exclude_from_explicit_instantiation__)), or potentially __attribute__ ((__always_inline__))).

When the whole class is marked dllimport, clang doesn't seem to react to these attributes at all.

This is a big practical problem for the method std::filesystem::path::u8string. The method is marked with _LIBCPP_INLINE_VISIBILITY, but ends up exported/imported nevertheless.

In C++17, this method returns a basic_string<char>, while in C++20 it returns a basic_string<char8_t>. With itanium name mangling, the return type of a method isn't included in the signature, but with MSVC C++ name mangling, the two versions of the method are distinctly different.

So despite the best efforts, a DLL build of the library exports the function u8string (with whichever return type it had when the lib was built), and a caller that is built with a different language version will fail to link as it tries to import the symbol from the DLL.

A small testcase of the issue looks like this:

extern "C" void externFunc(void *ptr);

class __declspec(dllimport) MyClass {
public:
     void inline
     __attribute__ ((__always_inline__))
     __attribute__ ((__exclude_from_explicit_instantiation__))
     inlineFunc() {
         externFunc(this);
     }
};

void caller(MyClass *obj) {
    obj->inlineFunc();
}

When building an object file out of this, it ends up with an extern call to __imp_<decoration>inlineFunc. (The rules for dllexport/import are different in mingw mode, where it ends up behaving as hoped/intended.)

Is there any way around this, to mark that we really, really, want to inline any call to this method, despite being in a dllimported class?

// Martin

I think this is basically https://bugs.llvm.org/show_bug.cgi?id=41018 , which just needs fixing.

Building libc++ with dllexportInlines- might also work (https://blog.llvm.org/2018/11/30-faster-windows-builds-with-clang-cl_14.html).

Hi,

I think this is basically 41018 – dllimport conflicts with exclude_from_explicit_instantiation. ,
which just needs fixing.

Thanks! That's indeed exactly the issue I'm observing, with lots of to-the-point commentery.

Building libc++ with dllexportInlines- might also work(https://blog.llvm.org/2018/11/30-faster-windows-builds-with-clang-cl_14.ht
ml).

In this case, it's the callers that need to be built with that flag, not the lib itself. But yeah, that's probably the best workaround for now.

// Martin