Author: Nerixyz Date: 2026-08-31T18:19:07+02:00 New Revision: 51e608f5ed8c799a7b61dd55496db984222b44d4
URL: https://github.com/llvm/llvm-project/commit/51e608f5ed8c799a7b61dd55496db984222b44d4 DIFF: https://github.com/llvm/llvm-project/commit/51e608f5ed8c799a7b61dd55496db984222b44d4.diff LOG: [lldb][MSABI] Take offset of vbptr into account (#190679) In the MS ABI, the offset found in the virtual base table is relative to the virtual base pointer. See Clang's `MicrosoftCXXABI::emitVBTableDefinition`: https://github.com/llvm/llvm-project/blob/1a0ca1019d214a24b55a45704dc71fa183672362/clang/lib/CodeGen/MicrosoftCXXABI.cpp#L2247-L2261 We previously assumed the offset was relative to the record's start. For example for `B` in ```cpp struct Extra { int e1 = 1; }; struct A { int a = 3; }; struct B : public Extra, public virtual A { int b = 4; }; ``` the `vbptr` is at offset 8 and inside that table, the offset for `A` is 16 while `A` sits at offset 24 from `B`'s start: ``` > cl main.cpp /GS- /Z7 /nologo /d1reportSingleClassLayoutB (...) class B size(32): +--- 0 | +--- (base class Extra) 0 | | e1 | +--- 8 | {vbptr} 16 | b | <alignment member> (size=4) | <alignment member> (size=4) +--- +--- (virtual base A) 24 | a +--- B::$vbtable@: 0 | -8 1 | 16 (Bd(B+8)A) (<- value we read) ``` Added: Modified: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp lldb/test/API/lang/cpp/diamond/TestCppDiamond.py lldb/test/API/lang/cpp/diamond/main.cpp Removed: ################################################################################ diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index f11e78d4b008c..b0cebd12598dd 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -313,6 +313,8 @@ static bool GetVBaseBitOffset(VTableContextBase &vtable_ctx, if (base_offset == INT64_MAX) return false; + if (vtable_ctx.isMicrosoft()) + base_offset += record_layout.getVBPtrOffset().getQuantity(); bit_offset = base_offset * 8; return true; diff --git a/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py b/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py index 27062c0666a1a..edb60922934de 100644 --- a/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py +++ b/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py @@ -107,6 +107,37 @@ def test(self): # Use variable paths to access the members. self.expect_var_path("j1.x", type="long", value="1") + children = [ + ValueCheck( + type="Extra", + children=[ + ValueCheck( + type="short", + name="some_value", + value="3", + ) + ], + ), + ValueCheck( + type="VBase", + children=[ValueCheck(type="int", name="m_value", value="12347")], + ), + ValueCheck( + type="Derived1", + children=[ + ValueCheck( + type="VBase", + children=[ + ValueCheck(type="int", name="m_value", value="12347") + ], + ) + ], + ), + ValueCheck(type="long", name="z", value="4"), + ] + # Test that the virtual bases are correct when v(b)table pointer is offset. + self.expect_expr("j3", result_type="Joiner3", result_children=children) + @expectedFailureAll @no_debug_info_test def test_invalid_member(self): diff --git a/lldb/test/API/lang/cpp/diamond/main.cpp b/lldb/test/API/lang/cpp/diamond/main.cpp index fdf2f3d326747..b9546e7a52c9b 100644 --- a/lldb/test/API/lang/cpp/diamond/main.cpp +++ b/lldb/test/API/lang/cpp/diamond/main.cpp @@ -20,9 +20,18 @@ struct Joiner2 : public Derived2 { long y = 2; }; +struct Extra { + short some_value = 3; +}; + +struct Joiner3 : public Extra, public virtual VBase, public Derived1 { + long z = 4; +}; + int main(int argc, const char *argv[]) { Joiner1 j1; Joiner2 j2; + Joiner3 j3; Derived2 *d = &j1; d = &j2; // breakpoint 1 return 0; // breakpoint 2 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
