<html>
<head>
<base href="https://llvm.org/bugs/" />
</head>
<body><span class="vcard"><a class="email" href="mailto:rnk@google.com" title="Reid Kleckner <rnk@google.com>"> <span class="fn">Reid Kleckner</span></a>
</span> changed
<a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED INVALID - novtable support"
href="https://llvm.org/bugs/show_bug.cgi?id=26905">bug 26905</a>
<br>
<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>What</th>
<th>Removed</th>
<th>Added</th>
</tr>
<tr>
<td style="text-align:right;">Status</td>
<td>NEW
</td>
<td>RESOLVED
</td>
</tr>
<tr>
<td style="text-align:right;">CC</td>
<td>
</td>
<td>rnk@google.com
</td>
</tr>
<tr>
<td style="text-align:right;">Resolution</td>
<td>---
</td>
<td>INVALID
</td>
</tr></table>
<p>
<div>
<b><a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED INVALID - novtable support"
href="https://llvm.org/bugs/show_bug.cgi?id=26905#c1">Comment # 1</a>
on <a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED INVALID - novtable support"
href="https://llvm.org/bugs/show_bug.cgi?id=26905">bug 26905</a>
from <span class="vcard"><a class="email" href="mailto:rnk@google.com" title="Reid Kleckner <rnk@google.com>"> <span class="fn">Reid Kleckner</span></a>
</span></b>
<pre>Your program is working because MSVC aggressively devirtualizes method calls in
constructors. Consider this reduction and the code generated by both compilers:
$ cat t.cpp
struct __declspec(novtable) A { A(); virtual void Init() = 0; };
struct __declspec(novtable) B : A { B(); void Init(); };
B::B() { this->Init(); }
$ clang -S t.cpp -o -
...
movq %rcx, 48(%rsp)
movq %rcx, 40(%rsp) # 8-byte Spill
callq "??0A@@QEAA@XZ"
movq 40(%rsp), %rcx # 8-byte Reload
movq (%rcx), %rdx
movq (%rdx), %rdx
movq %rax, 32(%rsp) # 8-byte Spill
callq *%rdx
$ cl -c t.cpp -Facl.asm && cat cl.asm
...
mov QWORD PTR [rsp+8], rcx
sub rsp, 40 ; 00000028H
mov rcx, QWORD PTR this$[rsp]
call ??0A@@QEAA@XZ ; A::A
mov rcx, QWORD PTR this$[rsp]
call ?Init@B@@UEAAXXZ ; B::Init
mov rax, QWORD PTR this$[rsp]
add rsp, 40 ; 00000028H
ret 0
The difference is that Clang's constructor for IteratedHashWithStaticTransform
is doing a virtual call for IteratedHashWithStaticTransform::Init, instead of
doing a direct call. If you annotate this class with declspec(novtable), then
the vptr slot is not initialized, and you will crash.
To me, the user is misusing novtable by applying it to a non-abstract class. If
you changed the source program slightly to invoke another virtual method from
within 'Init', your program would crash with MSVC as well.</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>