Index: test/cfi/two-vcalls.cpp =================================================================== --- /dev/null +++ test/cfi/two-vcalls.cpp @@ -0,0 +1,61 @@ +// RUN: %clangxx_cfi_diag -o %t %s +// RUN: %t 2>&1 | FileCheck %s + +// This test checks that we don't generate two type checks, +// if two virtual calls are in the same function. + +// UNSUPPORTED: win32 +// REQUIRES: cxxabi + +// TODO(krasin): implement the optimization to not emit +// two type checks. +// XFAIL: * +#include + +class Base { + public: + virtual void Foo() { + fprintf(stderr, "Base::Foo\n"); + } + + virtual void Bar() { + fprintf(stderr, "Base::Bar\n"); + } +}; + +class Derived : public Base { + public: + void Foo() override { + fprintf(stderr, "Derived::Foo\n"); + } + + void Bar() override { + printf("Derived::Bar\n"); + } +}; + +__attribute__((noinline)) void print(Base* ptr) { + ptr->Foo(); + // Corrupt the vtable pointer. We expect that the optimization will + // check vtable before the first vcall then store it in a local + // variable, and reuse it for the second vcall. With no optimization, + // CFI will complain about the virtual table being corrupted. + *reinterpret_cast(ptr) = 0; + ptr->Bar(); +} + + +int main() { + Base b; + Derived d; + // CHECK: Base::Foo + // CHECK: Base::Bar + print(&b); + + // CHECK: Derived::Foo + // CHECK-NOT: runtime error + // CHECK: Derived::Bar + print(&d); + + return 0; +}