[llvm-bugs] [Bug 36952] New: [MS] Clang fails to emit vftable adjustor thunks when parameter types are incomplete
via llvm-bugs
llvm-bugs at lists.llvm.org
Thu Mar 29 15:02:56 PDT 2018
https://bugs.llvm.org/show_bug.cgi?id=36952
Bug ID: 36952
Summary: [MS] Clang fails to emit vftable adjustor thunks when
parameter types are incomplete
Product: clang
Version: unspecified
Hardware: PC
OS: Windows NT
Status: NEW
Severity: enhancement
Priority: P
Component: LLVM Codegen
Assignee: unassignedclangbugs at nondot.org
Reporter: rnk at google.com
CC: llvm-bugs at lists.llvm.org
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 at B@@W7EAAXUIncomplete@@@Z)
t.exe : fatal error LNK1120: 1 unresolved externals
Reduced from https://crbug.com/822202.
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.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20180329/2c627292/attachment.html>
More information about the llvm-bugs
mailing list