| Issue |
203127
|
| Summary |
LLDB does not handle pointer-to-member-function correctly in C++
|
| Labels |
lldb
|
| Assignees |
bulbazord
|
| Reporter |
bulbazord
|
Disclaimer: This issue primarily talks about the representation of pointer-to-member-functions in the Itanium ABI. I have not looked into MSVC, but I would not be shocked if there are problems there as well.
Pointer to member functions (i.e. PMFs) are represented as 2 pointer-sized values (i.e. `sizeof(PMF) == 2 * sizeof(void *)`). What these values contain heavily depends on exactly how the PMF is formed. I've identified at least 5 scenarios where the semantics differ.
Given this program:
```cpp
#include <cstdio>
struct Base1 {
void nv1() {}
virtual void v1() {}
};
struct Base2 {
void nv2() {}
virtual void v2() {}
virtual void v3() {}
};
struct Derived : Base1, Base2 {
void v2() override {};
};
int main() {
// 1. Null PMF
void (Derived::*p1)() = nullptr;
// 2. Non-virtual without this-adjustment.
void (Derived::*p2)() = &Base1::nv1;
// 3. Non-virtual with this-adjustment.
void (Derived::*p3)() = &Base2::nv2;
// 4. Virtual without this-adjustment
void (Derived::*p4)() = &Derived::v1;
// 5. Virtual with this adjustment.
void (Derived::*p5)() = &Derived::v3;
return 0;
}
```
Compile it with clang via `clang -g foo.cpp -o foo`.
Then use LLDB to dump the values:
```
(lldb) v p1
(void (Derived::*)()) p1 = 0x00000000000000000000000000000000
(lldb) v p2
(void (Derived::*)()) p2 = 0x00000000000000000000000100000430 (member-pointers`Base1::nv1() at member-pointers.cpp:4)
(lldb) v p3
(void (Derived::*)()) p3 = 0x00000000000000100000000100000440 (member-pointers`Base2::nv2() at member-pointers.cpp:9)
(lldb) v p4
(void (Derived::*)()) p4 = 0x00000000000000010000000000000000
(lldb) v p5
(void (Derived::*)()) p5 = 0x00000000000000110000000000000008
```
LLDB is printing out these values as addresses. *PMFs are not like regular pointers* and do not necessarily correspond to a load address. PMFs are made up a "function" value and an "adjustment" value. The function value differs based on if the function is virtual: non-virtual functions get a function pointer and virtual functions use the field to contain a VTable offset. The adjustment value tells you how much the "this" pointer needs to be adjusted.
Running through the scenarios, here is what we see:
1. Null PMF, all fields 0.
2. Non-virtual pointer to `Base1::nv1`. Base1 is the first object in Derived, so it's just a function pointer with no `this` adjustment.
3. Non-virtual pointer to `Base2::nv2`. Base2 is the second object in Derived, so when you call `p2` with a Derived object, `this` must be adjusted by 8 bytes.
4. Pointer to `v1`. Base1 is the first object in Derived, so its virtual methods should be at the start of Derived's vtable. vtable offset is 0, this-adjustment is 0.
5. Pointer to `v3`. Base2 is the second object in Derived, so its virtual methods should be further down in Derived's vtable. vtable offset of 8, this-adjustment is 8.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs