[llvm-dev] [UPDATE] Disabling inline compilation (Clang with VS2019)

Hans Wennborg via llvm-dev
Tue, 07 Dec 2021 16:12:33 -0000

Adding a note here: https://reviews.llvm.org/D115252

On Mon, Dec 6, 2021 at 7:38 PM Reid Kleckner via llvm-dev
<llvm-dev at lists.llvm.org> wrote:
>
> Thanks for asking about the rules. I think, at the moment, we should leave
clang's dllimport+inline heuristics alone, but we should at least document
our behavior, perhaps in AttributeReference.html.
>
> On Fri, Dec 3, 2021 at 8:21 AM John Emmas via llvm-dev <llvm-dev at
lists.llvm.org> wrote:
>>
>> Just an update to a long gone thread....
>>
>> Back in September I flagged up some problematic code which was building
fine with MSVC but failing to link when built with Visual Studio and Clang. In
the end, it turned out to be a typo at my end but along the way we discovered a
difference in the way that MSVC and Clang will each treat functions declared
using '__declspec(dllimport) '  Basically, Clang was sometimes trying to
inline them when MSVC wasn't (I've added the relevant part of the
discussion below...)
>>
>> The devs here said they'd be happy to make Clang's behaviour
match MSVC but that it was traditionally hard to find out what Visual
Studio's 'rules' are.  So I posted a question on the VS developer
forum - and 3 months later, Microsoft's own devs have finally replied:-
>>
>>
https://developercommunity.visualstudio.com/t/__declspecdllimport-and-inline-abili/1537756#T-ND1602459
>>
>> I know it's ancient history now but given that the situation's
been clarified at last, I figured I might as well feed it back here.  Basically,
although the rules can change over time, currently (for dllimport functions)
MSVC carries out 2 simple tests when deciding whether or not they can be
candidates for inlining:-
>>
>>     1) the MSVC optimizer won't inline a candidate if that
candidate calls some other function - and/or
>>
>>     2) the MSVC optimizer won't inline a candidate if that
candidate accesses a global variable
>>
>> For class variables, a static member is treated as being a global
variable.
>>
>> Like I said, I know it's all a long gone problem but I figured
Microsoft's reply would be worth flagging up.  Hope it all helps,
>>
>> John
>>
>>
>> On 22/09/2021 13:53, Eric Astor wrote:
>>
>> 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:
https://godbolt.org/z/vTrEevY8o
>>
>> Just as John suggested, disassembling the output shows that clang is
inlining this function, even at -O1, where MSVC doesn't, even at /O3.
>>
>> I'd agree that this isn't a great match, though it *is* a point
of ambiguity in the handling of __declspec(dllimport).
>>
>>
>>> On 22/09/2021 13:22, John Emmas wrote:
>>>
>>> Hi there - I first asked this question over on clang-users but I
got advised to ask it here (sorry about the length...)
>>>
>>> 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:-
>>>
>>> #if defined (BUILDING_DLL)
>>>   #define DLL_API __declspec(dllexport)
>>> #else
>>>   #define DLL_API __declspec(dllimport)
>>> #endif
>>>
>>> namespace Gtkmm2ext {
>>>
>>>   class DLL_API Keyboard
>>>   {
>>>     public:
>>>       Keyboard ();
>>>       ~Keyboard ();
>>>
>>>       static Keyboard& get_keyboard() { return *_the_keyboard;
}
>>>
>>>     protected:
>>>       static Keyboard* _the_keyboard;
>>>   };
>>>
>>> } /* namespace */
>>>
>>> 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'
>>>
>>> But here's the thing... '_the_keyboard' is an internal
variable that's private to the DLL. It should never need to get accessed by
the exe.  If I change 'get_keyboard()' to be just a declaration (and
then implement it in a DLL source file) Clang is then happy - but unfortunately,
this is one of several hundred similar linker errors.
>>>
>>> So I'm wondering if (maybe) the compiler implemented its call
to 'get_keyboard()' as inline code, rather than importing it from the
DLL?  Maybe for very simple code like this, Clang is trying to be clever and
implement stuff inline if it can?
>>>
>>> VS2019 can disable inline code via a compiler option called
"/Ob0" - and typing "clang-cl /?" indicates that
"/Ob0" is supported.   But I still see the error, even if I specify
"/Ob0" during compilation.
>>>
>>> So will "/Ob0" disable all inline compilation for Clang?
Or does it only take effect where there's an actual 'inline'
keyword?  Hope that all makes sense...
>>>
>>> John
>>>
>>>
>>
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev