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
14class Base {
15 public:
16 virtual void Foo() {
17 fprintf(stderr, format: "Base::Foo\n");
18 }
19
20 virtual void Bar() {
21 fprintf(stderr, format: "Base::Bar\n");
22 }
23};
24
25class Derived : public Base {
26 public:
27 void Foo() override {
28 fprintf(stderr, format: "Derived::Foo\n");
29 }
30
31 void Bar() override {
32 printf(format: "Derived::Bar\n");
33 }
34};
35
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
47int main() {
48 Base b;
49 Derived d;
50 // CHECK: Base::Foo
51 // CHECK: Base::Bar
52 print(ptr: &b);
53
54 // CHECK: Derived::Foo
55 // CHECK-NOT: runtime error
56 // CHECK: Derived::Bar
57 print(ptr: &d);
58
59 return 0;
60}
61

source code of compiler-rt/test/cfi/two-vcalls.cpp