<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - LLD's /msvclto fails to export some template functions when bitcode files disagree about dllexport"
   href="https://bugs.llvm.org/show_bug.cgi?id=32334">32334</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>LLD's /msvclto fails to export some template functions when bitcode files disagree about dllexport
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>lld
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Windows NT
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>COFF
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>rnk@google.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Consider:

$ cat a.cpp
template <typename T> struct X { void foo() {} };
template struct X<int>;

$ cat b.cpp
template <typename T> struct X { void foo() {} };
struct __declspec(dllexport) B : X<int> { void bar() { foo(); } };

$ clang -flto -fuse-ld=lld a.cpp b.cpp -shared -o t.dll && dumpbin -exports
t.dll | grep foo
          6    5 0000E000 ?foo@?$X@H@@QEAAXXZ

$ clang -flto -fuse-ld=lld a.cpp b.cpp -shared -o t.dll -Wl,-msvclto && dumpbin
-exports t.dll | grep foo
   Creating library t.lib and object t.exp
# nothing

The resulting DLL does not export X<int>::foo.

---

This raises questions about our choice of representation for dllexport. Here
are the two prototypes from the IR:
define weak_odr void @"\01?foo@?$X@H@@QEAAXXZ"(%struct.X* %this)
define weak_odr dllexport void @"\01?foo@?$X@H@@QEAAXXZ"(%struct.X* %this)

Note the dllexport mismatch. The linkage says these things are ODR, but their
dll storage class doesn't match. Is that a problem?

In COFF, exports are identified by a list of /export flags in the .drective
section, so when a comdat section is discarded, we don't lose the information
that the symbol might be exported. It would be possible to generate LLVM IR
like this, where we never use the dllexport storage class and only use the
"Linker Options" module flag to store /export flags. This might solve the
possible ODR violation described above, and would fix this bug.

Personally, I'm not in favor of the change above, but it's worth discussing as
a possible redesign.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>