Open llvmbot opened 4 years ago
Example with memcmp and a placement new:
struct X { virtual void foo() { puts("foo"); } };
struct Y { virtual void bar() { puts("bar"); } };
static_assert(sizeof(X) == sizeof(Y));
int main() { Y q = new Y; X p = new (q) X;
if (memcmp(&p, &q, sizeof p) == 0)
p->foo();
Example with memcpy and a dead dynamic variable:
struct X { virtual void foo() { puts("foo"); } };
struct Y { virtual void bar() { puts("bar"); } };
attribute((optnone)) // imagine it in a separate TU static void opaque(void p) { return p; }
int main() { unsigned long u, v;
Y *q = new Y;
opaque(q);
memcpy(&v, &q, sizeof v);
delete q;
X *p = new X;
opaque(p);
memcpy(&u, &p, sizeof u);
if (u == v)
p->foo();
There is a similar example with memcpy and a dead local. Please let me know if it's worth adding it here.
Extended Description
This is based on bug 34548, comment 49, and bug 44313. It seems there was an effort to fix the problem as it applies to devirtualization independently from the general case, so filing this separately. As mentioned in the referenced comment, GVN changes a pointer to an older one inside the
if
(it doesn't matter which pointer is on the left in the comparison and which one is on the right). Visible only with -fstrict-vtable-pointers.Devirtualization seems not to be concerned with past-the-end pointers and with
restrict
, so the focus is on the case of a living object located at the same place where another, now dead, object was located, e.g.:It seems comparison of naked pointers and casts to integers are handled. What I spotted missing:
Example with pointers to a class without virtual tables and a placement new:
include
include
struct B { void m() {} };
struct X : B { virtual void foo() { puts("foo"); } };
struct Y : B { virtual void bar() { puts("bar"); } };
static_assert(sizeof(X) == sizeof(Y));
int main() { B q = new Y; X p = new (q) X;
}
$ clang++ -std=c++2a -Wall -fstrict-vtable-pointers test.cc && ./a.out foo $ clang++ -std=c++2a -Wall -fstrict-vtable-pointers -O3 test.cc && ./a.out bar
clang x86-64 version: clang version 10.0.0 (https://github.com/llvm/llvm-project.git c5fb73c5d1b3f1adb77d99fc85c594b48bff08f9)