1 // RUN: %clangxx_cfi_diag -o %t %s 2 // RUN: %run %t 2>&1 | FileCheck %s 3 4 // This test checks that we don't generate two type checks, 5 // if two virtual calls are in the same function. 6 7 // UNSUPPORTED: target={{.*windows-msvc.*}} 8 // REQUIRES: cxxabi 9 10 // TODO(krasin): implement the optimization to not emit two type checks. 11 // XFAIL: * 12 #include <stdio.h> 13 14 class Base { 15 public: Foo()16 virtual void Foo() { 17 fprintf(stderr, "Base::Foo\n"); 18 } 19 Bar()20 virtual void Bar() { 21 fprintf(stderr, "Base::Bar\n"); 22 } 23 }; 24 25 class Derived : public Base { 26 public: Foo()27 void Foo() override { 28 fprintf(stderr, "Derived::Foo\n"); 29 } 30 Bar()31 void Bar() override { 32 printf("Derived::Bar\n"); 33 } 34 }; 35 print(Base * ptr)36__attribute__((noinline)) void print(Base* ptr) { 37 ptr->Foo(); 38 // Corrupt the vtable pointer. We expect that the optimization will 39 // check vtable before the first vcall then store it in a local 40 // variable, and reuse it for the second vcall. With no optimization, 41 // CFI will complain about the virtual table being corrupted. 42 *reinterpret_cast<void**>(ptr) = 0; 43 ptr->Bar(); 44 } 45 46 main()47int main() { 48 Base b; 49 Derived d; 50 // CHECK: Base::Foo 51 // CHECK: Base::Bar 52 print(&b); 53 54 // CHECK: Derived::Foo 55 // CHECK-NOT: runtime error 56 // CHECK: Derived::Bar 57 print(&d); 58 59 return 0; 60 } 61