<div dir="ltr">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 <a href="https://clang.llvm.org/docs/AttributeReference.html">AttributeReference.html</a>.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Dec 3, 2021 at 8:21 AM John Emmas 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">
  
    
  
  <div>
    <div>Just an update to a long gone
      thread....<br>
      <br>
      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...)<br>
      <br>
      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:-<br>
      <br>
      <a href="https://developercommunity.visualstudio.com/t/__declspecdllimport-and-inline-abili/1537756#T-ND1602459" target="_blank">https://developercommunity.visualstudio.com/t/__declspecdllimport-and-inline-abili/1537756#T-ND1602459</a><br>
      <br>
      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:-<br>
      <br>
          1) the MSVC optimizer won't inline a candidate if that
      candidate calls some other function - and/or<br>
      <br>
          2) the MSVC optimizer won't inline a candidate if that
      candidate accesses a global variable<br>
      <br>
      For class variables, a static member is treated as being a global
      variable.<br>
      <br>
      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,<br>
      <br>
      John<br>
      <br>
      <br>
      On 22/09/2021 13:53, Eric Astor wrote:<br>
    </div>
    <blockquote type="cite">
      
      <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" target="_blank">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>
          <br>
        </div>
        <div class="gmail_quote">
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
            <div>On 22/09/2021 13:22, John Emmas
              wrote:<br>
            </div>
            <blockquote type="cite">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>
              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. <br>
              <br>
              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? <br>
              <br>
              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. <br>
              <br>
              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... <br>
              <br>
              John </blockquote>
            <br>
          </blockquote>
        </div>
      </div>
    </blockquote>
    <br>
  </div>
_______________________________________________<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>