<div dir="ltr"><div dir="ltr"><div>I've transferred John's example into Compiler Explorer, which will hopefully be a useful demonstration. Both clang and MSVC handle the dllexport case identically... but they do differ in the dllimport case: <a href="https://godbolt.org/z/vTrEevY8o">https://godbolt.org/z/vTrEevY8o</a></div><div><br></div><div>Just as John suggested, disassembling the output shows that clang is inlining this function, even at -O1, where MSVC doesn't, even at /O3.</div><div><br></div><div>I'd agree that this isn't a great match, though it *is* a point of ambiguity in the handling of __declspec(dllimport).</div><div><br></div><div>One possible workaround: add a noinline marker on functions defined in headers that need to access protected members. (<a href="https://godbolt.org/z/Pe67ovMnP">https://godbolt.org/z/Pe67ovMnP</a>)</div><div>IMO, the best option would be to just adopt the policy that you don't define DLL_API functions in headers... which I would suggest is the best option anyway, since you don't want your importing code to have the definition.<br></div></div><div><br></div><div>Either way, we should probably decide how we want clang to behave in this case. It's possible we should treat anything marked as __declspec(dllimport) as defined externally, and ignore any definition present in the source code?<br></div><div><br></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Sep 22, 2021 at 8:33 AM Dimitry Andric via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-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">On 22 Sep 2021, at 14:22, John Emmas via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br>
> <br>
> Hi there - I first asked this question over on clang-users but I got advised to ask it here (sorry about the length...)<br>
> <br>
> I'm a VS2019 user and I've been trying to switch it here to use Clang as the compiler, rather than MSVC. But I seem to have hit a common problem. Consider the following code:-<br>
> <br>
> #if defined (BUILDING_DLL)<br>
> #define DLL_API __declspec(dllexport)<br>
> #else<br>
> #define DLL_API __declspec(dllimport)<br>
> #endif<br>
> <br>
> namespace Gtkmm2ext {<br>
> <br>
> class DLL_API Keyboard<br>
> {<br>
> public:<br>
> Keyboard ();<br>
> ~Keyboard ();<br>
> <br>
> static Keyboard& get_keyboard() { return *_the_keyboard; }<br>
> <br>
> protected:<br>
> static Keyboard* _the_keyboard;<br>
> };<br>
> <br>
> } /* namespace */<br>
> <br>
> The above code is from a DLL which gets used by an exe. The DLL compiles and links just fine and the exe compiles. But when I try to link the exe, Clang's linker complains that it can't find '_the_keyboard'<br>
<br>
As far as I understand it, if you specify __declspec(dllexport) for a whole class, then *all* members, including statics, get explicitly exported in the DLL image.<br>
<br>
I.e. it is as if you had manually specified __declspec(dllexport) to each and every member. I don't know if there is any way to override that for just a single class member, for example as with gcc you could add a __attribute__((visibility("hidden"))) to one of them.<br>
<br>
So maybe you can selectively add DLL_API to those class members that you need exported, as described here:<br>
<a href="https://docs.microsoft.com/en-us/cpp/cpp/using-dllimport-and-dllexport-in-cpp-classes?view=msvc-160#_pluslang_using_dllimport_and_dllexport_in_c2b2bselectivememberimportexport" rel="noreferrer" target="_blank">https://docs.microsoft.com/en-us/cpp/cpp/using-dllimport-and-dllexport-in-cpp-classes?view=msvc-160#_pluslang_using_dllimport_and_dllexport_in_c2b2bselectivememberimportexport</a><br>
<br>
-Dimitry<br>
<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div></div>