<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 - Implement a new dllexport/dllimport variant that doesn't apply to class inline functions"
   href="https://bugs.llvm.org/show_bug.cgi?id=33628">33628</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Implement a new dllexport/dllimport variant that doesn't apply to class inline functions
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </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>Frontend
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@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>Exporting all inline functions of a class with many inline functions can be
very expensive because they will appear in every object file that includes the
header. Here's an example of what this looks like:

$ cat t.cpp
struct __declspec(dllexport) Foo {
  void f() {}
  void g() {}
};

$ cl -c t.cpp && llvm-nm t.obj
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

t.cpp
00000000 T ??4Foo@@QEAAAEAU0@$$QEAU0@@Z
00000000 T ??4Foo@@QEAAAEAU0@AEBU0@@Z
00000000 T ?f@Foo@@QEAAXXZ
00000000 T ?g@Foo@@QEAAXXZ
01055e97 a @comp.id
80000190 a @feat.00

t.cpp doesn't have to reference Foo or it's inline functions in any way to get
all of these symbols, so Foo's inline functions will be emitted in every file
that uses its header. This is necessary for ABI compatibility with MSVC, so we
can't change our behavior here.

Other platforms that use visibility have the similar but different problem that
deduplicating default visibility inline functions at runtime is expensive. One
solution is to use -fvisibility-inlines-hidden, which compromises the C++
language guarantee that function addresses are unique across the whole program.
This flag is fairly widely used, which suggests this is a reasonable compromise
for many users.

I don't think we want a flag to control this behavior for dllexport, because it
would be totally ABI incompatible with MSVC. So, instead, I propose that we add
a new attribute that only applies to classes, and has the semantics that it
doesn't propagate to inline methods. We could call this
dll(export|import)_noninline.

I think our heuristic for applying dllexport should only rely on the contents
of the class body. This means that methods that are declared inline after the
end of the class body will be exported. The user can suppress this behavior by
adding the 'inline' keyword to the in-class declaration. Here's what this looks
like:

struct __declspec(dllexport_noninline) Foo { void f(); };
inline void Foo::f() {} // will be exported, we thought it was not inline

struct __declspec(dllexport_noninline) Bar { inline void f(); };
inline void Bar::f() {} // will NOT be exported, we knew it was inline at class
end</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>