<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 - [MS] Clang fails to emit vftable adjustor thunks when parameter types are incomplete"
   href="https://bugs.llvm.org/show_bug.cgi?id=36952">36952</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[MS] Clang fails to emit vftable adjustor thunks when parameter types are incomplete
          </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>LLVM Codegen
          </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>Consider:

$ cat t.h
struct Incomplete;
struct A {
  virtual void foo(Incomplete p) = 0;
};
struct B : virtual A {
  void foo(Incomplete p) override;
};
struct C : B { int c; };

$ cat a.cpp
#include "t.h"
int main() { C c; }

$ cat b.cpp
#include "t.h"
struct Incomplete { void *p; };
void B::foo(Incomplete p) {}

This should produce a valid C++ program, but with clang we get link errors:

$ clang-cl -c a.cpp b.cpp && link -nologo a.obj b.obj -out:t.exe  && ./t.exe
a.obj : error LNK2001: unresolved external symbol "[thunk]:public: virtual void
__cdecl B::foo`adjustor{8}' (struct Incomplete)"
(?foo@B@@W7EAAXUIncomplete@@@Z)
t.exe : fatal error LNK1120: 1 unresolved externals

Reduced from <a href="https://crbug.com/822202">https://crbug.com/822202</a>.

Here are the record layouts:

*** Dumping AST Record Layout
         0 | struct B
         0 |   (B vbtable pointer)
         8 |   struct A (virtual base)
         8 |     (A vftable pointer)
           | [sizeof=16, align=8,
           |  nvsize=8, nvalign=8]

*** Dumping AST Record Layout
         0 | struct C
         0 |   struct B (base)
         0 |     (B vbtable pointer)
         8 |   int c
        16 |   struct A (virtual base)
        16 |     (A vftable pointer)
           | [sizeof=24, align=8,
           |  nvsize=16, nvalign=8]

The primary definition of 'B::foo' hardcodes a -8 this adjustment, which
adjusts from A-in-B to the beginning of B.

A is a virtual base, so its location changes relative to B in C's layout. In
C's layout, the offset from A to B is -16, not -8.

C's vftable slot for 'foo' needs to use a thunk to do an additional 8 byte
adjustment so that -8 - 8 = -16, and B::foo's 'this' argument is correctly
positioned. That's where "adjustor{8}" symbol comes from.

So far, Clang implements all that stuff correctly.

The link error comes from the fact we don't have a definition for the
Incomplete struct in a.cpp, so we give up when attempting to emit the thunk
that does the adjustment. We don't emit an error because this code was
originally written to support available_externally vtables for Itanium, so it
was just an optimization, not a correctness issue.

The fix is probably to abuse musttail to emit a thunk without knowing the
prototype for the virtual method.</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>