Fix VTableOverlay dtor wrapper & test bitcasts on 32-bit MSVC#1048
Fix VTableOverlay dtor wrapper & test bitcasts on 32-bit MSVC#1048aaronj0 wants to merge 1 commit into
Conversation
Add __thiscall to the bitcast type on _M_IX86 so the caller reproduces the compiler's virtual-dispatch ABI
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1048 +/- ##
=======================================
Coverage 86.73% 86.73%
=======================================
Files 23 23
Lines 5970 5972 +2
=======================================
+ Hits 5178 5180 +2
Misses 792 792
🚀 New features to boost your workflow:
|
| static VTableOverlayDtorSlotFn SlotToDtorFn(void* slot) { | ||
| static_assert(sizeof(VTableOverlayDtorSlotFn) >= sizeof(void*)); | ||
| VTableOverlayDtorSlotFn fn{}; | ||
| std::memcpy(&fn, &slot, sizeof(slot)); |
There was a problem hiding this comment.
warning: multilevel pointer conversion from 'void **' to 'const void *', please use explicit cast [bugprone-multi-level-implicit-pointer-conversion]
n fn{};
^| } | ||
| static void* DtorFnToSlot(VTableOverlayDtorSlotFn fn) { | ||
| void* slot; | ||
| std::memcpy(&slot, &fn, sizeof(slot)); |
There was a problem hiding this comment.
warning: multilevel pointer conversion from 'void **' to 'void *', please use explicit cast [bugprone-multi-level-implicit-pointer-conversion]
* slot;
^| static_cast<B*>(self)->m_d); | ||
| // Replacement functions installed into vtable slots. | ||
| struct Repl { | ||
| int negate(int x) { return -x; } |
There was a problem hiding this comment.
warning: method 'negate' can be made static [readability-convert-member-functions-to-static]
| int negate(int x) { return -x; } | |
| static int negate(int x) { return -x; } |
| // Replacement functions installed into vtable slots. | ||
| struct Repl { | ||
| int negate(int x) { return -x; } | ||
| int twice(int x) { return x * 2; } |
There was a problem hiding this comment.
warning: method 'twice' can be made static [readability-convert-member-functions-to-static]
| int twice(int x) { return x * 2; } | |
| static int twice(int x) { return x * 2; } |
| // Reads the object via `this`: layout is { vptr, int value } on every | ||
| // ABI we target, so the data member sits at sizeof(void*). | ||
| int read_value(int x) { | ||
| return *reinterpret_cast<int*>(reinterpret_cast<char*>(this) + |
There was a problem hiding this comment.
warning: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast]
return *reinterpret_cast<int*>(reinterpret_cast<char*>(this) +
^| // Reads the object via `this`: layout is { vptr, int value } on every | ||
| // ABI we target, so the data member sits at sizeof(void*). | ||
| int read_value(int x) { | ||
| return *reinterpret_cast<int*>(reinterpret_cast<char*>(this) + |
There was a problem hiding this comment.
warning: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast]
return *reinterpret_cast<int*>(reinterpret_cast<char*>(this) +
^| sizeof(void*)) + | ||
| x; | ||
| } | ||
| int foo() { return reinterpret_cast<A*>(this)->m_x + 10; } |
There was a problem hiding this comment.
warning: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast]
int foo() { return reinterpret_cast<A*>(this)->m_x + 10; }
^| } | ||
| int foo() { return reinterpret_cast<A*>(this)->m_x + 10; } | ||
| int bar() { | ||
| B* b = reinterpret_cast<B*>(this); |
There was a problem hiding this comment.
warning: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast]
B* b = reinterpret_cast<B*>(this);
^| template <class MFP> void* MethodAddr(MFP mfp) { | ||
| static_assert(sizeof(MFP) >= sizeof(void*), "unexpected MFP layout"); | ||
| void* addr; | ||
| std::memcpy(&addr, &mfp, sizeof(addr)); |
There was a problem hiding this comment.
warning: multilevel pointer conversion from 'void **' to 'void *', please use explicit cast [bugprone-multi-level-implicit-pointer-conversion]
std::memcpy(&addr, &mfp, sizeof(addr));
^
Add __thiscall to the bitcast type on _M_IX86 so the caller reproduces the compiler's virtual-dispatch ABI.
Fixes all failing tests of the VTableOverlay on 32-bit MSVC:
call_slot(inst, kBeta, 5)call_slot(inst, kAlpha, 5)call_slot(a, kBeta, 5)call_slot(inst, kAlpha, 5)call_slot(inst, kAlpha, 5)call_slot_no_arg(&a/&b, kAlpha)call_slot(inst, kBeta, 5)🤖 AI-assisted