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