multiple-inheritance.cpp revision 86277eb844c4983c81de62d7c050e92fe7155788
1// RUN: %clangxx_cfi -o %t %s
2// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
3// RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s
4
5// RUN: %clangxx_cfi -DB32 -o %t %s
6// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
7// RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s
8
9// RUN: %clangxx_cfi -DB64 -o %t %s
10// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
11// RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s
12
13// RUN: %clangxx_cfi -DBM -o %t %s
14// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
15// RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s
16
17// RUN: %clangxx -o %t %s
18// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s
19// RUN: %t x 2>&1 | FileCheck --check-prefix=NCFI %s
20
21// Tests that the CFI mechanism is sensitive to multiple inheritance and only
22// permits calls via virtual tables for the correct base class.
23
24#include <stdio.h>
25#include "utils.h"
26
27struct A {
28  virtual void f() = 0;
29};
30
31struct B {
32  virtual void g() = 0;
33};
34
35struct C : A, B {
36  virtual void f(), g();
37};
38
39void C::f() {}
40void C::g() {}
41
42int main(int argc, char **argv) {
43#ifdef B32
44  break_optimization(new Deriver<A, 0>);
45  break_optimization(new Deriver<B, 0>);
46#endif
47
48#ifdef B64
49  break_optimization(new Deriver<A, 0>);
50  break_optimization(new Deriver<A, 1>);
51  break_optimization(new Deriver<B, 0>);
52  break_optimization(new Deriver<B, 1>);
53#endif
54
55#ifdef BM
56  break_optimization(new Deriver<A, 0>);
57  break_optimization(new Deriver<A, 1>);
58  break_optimization(new Deriver<A, 2>);
59  break_optimization(new Deriver<B, 0>);
60  break_optimization(new Deriver<B, 1>);
61  break_optimization(new Deriver<B, 2>);
62#endif
63
64  C *c = new C;
65  break_optimization(c);
66
67  // CFI: 1
68  // NCFI: 1
69  fprintf(stderr, "1\n");
70
71  if (argc > 1) {
72    A *a = c;
73    ((B *)a)->g(); // UB here
74  } else {
75    B *b = c;
76    ((A *)b)->f(); // UB here
77  }
78
79  // CFI-NOT: 2
80  // NCFI: 2
81  fprintf(stderr, "2\n");
82}
83