[a1f0cb6] | 1 | #pragma once |
---|
| 2 | |
---|
| 3 | // inline virtual_dtor to have a virtual dtor. |
---|
[8512a2f] | 4 | // when using this, delete() is also virtual and will be called on the right address |
---|
| 5 | // using free() directly on polymorphic types may result in unaligned memory deallocation |
---|
| 6 | // in multi-inheritance or in single inheritance if the inline isn't the first field |
---|
| 7 | |
---|
| 8 | // This supports virtual dtors for both single and multiple inheritance, |
---|
| 9 | // however it does not support multiple inheritance of the virtual_dtor. e.g.: |
---|
| 10 | // given struct A { inline virtual_dtor; } and struct B { inline virtual_dtor; } |
---|
| 11 | // struct C { inline A; inline B; } will result in undefined behaviour |
---|
| 12 | struct virtual_dtor { |
---|
| 13 | void (*__virtual_dtor_ptr)(virtual_dtor &); |
---|
| 14 | void * __virtual_obj_start; |
---|
| 15 | }; |
---|
| 16 | |
---|
| 17 | // the following routines are used by the compiler and should not be called directly |
---|
| 18 | static inline void __CFA_set_virt_dtor( virtual_dtor & this, void (*v_dtor)(virtual_dtor &)) { |
---|
| 19 | this.__virtual_dtor_ptr = v_dtor; |
---|
| 20 | } |
---|
| 21 | static inline void __CFA_set_virt_start( virtual_dtor & this, void * start) { |
---|
| 22 | this.__virtual_obj_start = start; |
---|
| 23 | } |
---|
| 24 | static inline void __CFA_setup_dtor( virtual_dtor & this ) with(this) { |
---|
| 25 | __virtual_dtor_ptr = 0p; |
---|
| 26 | __virtual_obj_start = &this; |
---|
| 27 | } |
---|
[1e940de0] | 28 | static inline bool __CFA_dtor_shutdown( virtual_dtor & this ) with(this) { |
---|
| 29 | if ( __virtual_dtor_ptr == 1p ) return true; // stop base dtors from being called twice |
---|
[8512a2f] | 30 | if ( __virtual_dtor_ptr ) { |
---|
| 31 | void (*dtor_ptr)(virtual_dtor &) = __virtual_dtor_ptr; |
---|
| 32 | __virtual_dtor_ptr = 0p; |
---|
[1e940de0] | 33 | dtor_ptr(*((virtual_dtor *)__virtual_obj_start)); // call most derived dtor |
---|
| 34 | __virtual_dtor_ptr = 1p; // stop base dtors from being called twice |
---|
| 35 | return true; |
---|
[8512a2f] | 36 | } |
---|
[1e940de0] | 37 | return false; |
---|
[8512a2f] | 38 | } |
---|
| 39 | static inline void __CFA_virt_free( virtual_dtor & this ) { free( this.__virtual_obj_start ); } |
---|
| 40 | static inline void * __CFA_get_virt_start( virtual_dtor & this ) { return this.__virtual_obj_start; } |
---|
| 41 | static inline void ?{}( virtual_dtor & this ) {} |
---|
| 42 | static inline void ^?{}( virtual_dtor & this ) {} |
---|