@@ -30,6 +30,54 @@ struct Derived : Base1, Base0 {
3030 Derived (const Derived &) = delete ;
3131};
3232
33+ // ChatGPT-generated Diamond
34+
35+ struct VBase {
36+ virtual ~VBase () = default ;
37+ virtual int ping () const { return 1 ; }
38+ int vbase_tag = 42 ; // ensure it's not empty
39+ };
40+
41+ // Left/right add some weight to steer layout differences across compilers
42+ struct Left : virtual VBase {
43+ char pad_l[7 ];
44+ virtual ~Left () = default ;
45+ };
46+ struct Right : virtual VBase {
47+ long long pad_r;
48+ virtual ~Right () = default ;
49+ };
50+
51+ struct Diamond : Left, Right {
52+ Diamond () = default ;
53+ Diamond (const Diamond &) = default ;
54+ ~Diamond () override = default ;
55+ int ping () const override { return 7 ; }
56+ int self_tag = 99 ;
57+ };
58+
59+ // Factory that returns the *virtual base* type; this is the seam
60+ std::shared_ptr<VBase> make_diamond_as_vbase () {
61+ auto sp = std::make_shared<Diamond>();
62+ return sp; // upcast to VBase shared_ptr (virtual base)
63+ }
64+
65+ // For diagnostics / skip decisions in test
66+ struct DiamondAddrs {
67+ uintptr_t as_self;
68+ uintptr_t as_vbase;
69+ uintptr_t as_left;
70+ uintptr_t as_right;
71+ };
72+
73+ DiamondAddrs diamond_addrs () {
74+ auto sp = std::make_shared<Diamond>();
75+ return DiamondAddrs{reinterpret_cast <uintptr_t >(sp.get ()),
76+ reinterpret_cast <uintptr_t >(static_cast <VBase *>(sp.get ())),
77+ reinterpret_cast <uintptr_t >(static_cast <Left *>(sp.get ())),
78+ reinterpret_cast <uintptr_t >(static_cast <Right *>(sp.get ()))};
79+ }
80+
3381} // namespace test_class_sh_mi_thunks
3482
3583TEST_SUBMODULE (class_sh_mi_thunks, m) {
@@ -90,4 +138,23 @@ TEST_SUBMODULE(class_sh_mi_thunks, m) {
90138 }
91139 return obj_der->vec .size ();
92140 });
141+
142+ py::class_<VBase, py::smart_holder>(m, " VBase" ).def (" ping" , &VBase::ping);
143+
144+ py::class_<Left, VBase, py::smart_holder>(m, " Left" );
145+ py::class_<Right, VBase, py::smart_holder>(m, " Right" );
146+
147+ py::class_<Diamond, Left, Right, py::smart_holder>(m, " Diamond" , py::multiple_inheritance ())
148+ .def (py::init<>())
149+ .def (" ping" , &Diamond::ping);
150+
151+ m.def (" make_diamond_as_vbase" , &make_diamond_as_vbase);
152+
153+ py::class_<DiamondAddrs, py::smart_holder>(m, " DiamondAddrs" )
154+ .def_readonly (" as_self" , &DiamondAddrs::as_self)
155+ .def_readonly (" as_vbase" , &DiamondAddrs::as_vbase)
156+ .def_readonly (" as_left" , &DiamondAddrs::as_left)
157+ .def_readonly (" as_right" , &DiamondAddrs::as_right);
158+
159+ m.def (" diamond_addrs" , &diamond_addrs);
93160}
0 commit comments