[PATCH] D96976: [analyzer] Fix reinterpret_cast handling for pointer-to-member
Balázs Benics via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 1 03:08:36 PST 2021
steakhal requested changes to this revision.
steakhal added a comment.
This revision now requires changes to proceed.
I have serious concerns inline.
================
Comment at: clang/test/Analysis/reinterpret-cast-pointer-to-member.cpp:20
int DoubleDerived::*ddf = &Base::field;
int Base::*bf = reinterpret_cast<int Base::*>(reinterpret_cast<int Derived::*>(reinterpret_cast<int Base::*>(ddf)));
Base base;
----------------
Please have a note describing why you are doing this roundtrip.
================
Comment at: clang/test/Analysis/reinterpret-cast-pointer-to-member.cpp:29-31
+ Some some;
+ some.*sf = 14;
+ clang_analyzer_eval(some.*sf == 14); // expected-warning{{UNKNOWN}}
----------------
The assignment is actually UB.
TBH I don't know how to test such behavior xD
Same for the next example.
Shouldn't it return `undef` for reading via an invalid member pointer?
================
Comment at: clang/test/Analysis/reinterpret-cast-pointer-to-member.cpp:43-50
+struct A {};
+struct B : public A {};
+struct C {
+ int field;
+};
+struct D : public C {};
+struct E : public B, public D {};
----------------
An ASCII art would help so much:
```
A C(field)
| |
B D
\ /
E
|
F
```
However, I'm still missing a diamond-shaped inheritance.
================
Comment at: clang/test/Analysis/reinterpret-cast-pointer-to-member.cpp:52-62
+void testMultiple() {
+ int F::*f = &F::field;
+ int A::*a = reinterpret_cast<int A::*>(f);
+ int C::*c = reinterpret_cast<int C::*>(f);
+ A aobj;
+ C cobj;
+ aobj.*a = 13;
----------------
Wait a minute. It's not how it works.
How I imagine member pointers, they are just offsets.
`&F::field` is notionally equivalent with `offsetof(F, field)`. That being said, You can not apply this member pointer to any object besides `F`.
Imagine if the classes of the inheritance tree would have other fields as well.
Then the `offsetof(T, field)` would be different for `F`, and `C`.
This example demonstrates that both of these member pointer dereferences are UB.
https://godbolt.org/z/15sMEP
It returns different values depending on the optimization level, which is a clear sign of UB.
BTW this issue is closely related to strict aliasing.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D96976/new/
https://reviews.llvm.org/D96976
More information about the cfe-commits
mailing list