// UNSUPPORTED: target={{.*windows-msvc.*}}
// RUN: %clangxx_cfi -o %t %s
// RUN: %expect_crash %run %t a
// RUN: %expect_crash %run %t b
// RUN: %expect_crash %run %t c
// RUN: %expect_crash %run %t d
// RUN: %expect_crash %run %t e
// RUN: %run %t f
// RUN: %run %t g
// RUN: %clangxx_cfi_diag -o %t2 %s
// RUN: %run %t2 a 2>&1 | FileCheck --check-prefix=A %s
// RUN: %run %t2 b 2>&1 | FileCheck --check-prefix=B %s
// RUN: %run %t2 c 2>&1 | FileCheck --check-prefix=C %s
// RUN: %run %t2 d 2>&1 | FileCheck --check-prefix=D %s
// RUN: %run %t2 e 2>&1 | FileCheck --check-prefix=E %s
#include <assert.h>
#include <string.h>
struct SBase1 {
void b1() {}
};
struct SBase2 {
void b2() {}
};
struct S : SBase1, SBase2 {
void f1() {}
int f2() { return 1; }
virtual void g1() {}
virtual int g2() { return 1; }
virtual int g3() { return 1; }
};
struct T {
void f1() {}
int f2() { return 2; }
virtual void g1() {}
virtual int g2() { return 2; }
virtual void g3() {}
};
typedef void (S::*S_void)();
typedef int (S::*S_int)();
typedef int (T::*T_int)();
template <typename To, typename From>
To bitcast(From f) {
assert(sizeof(To) == sizeof(From));
To t;
memcpy(&t, &f, sizeof(f));
return t;
}
int main(int argc, char **argv) {
S s;
T t;
switch (argv[1][0]) {
case 'a':
// A: runtime error: control flow integrity check for type 'int (S::*)()' failed during non-virtual pointer to member function call
// A: note: S::f1() defined here
(s.*bitcast<S_int>(&S::f1))();
break;
case 'b':
// B: runtime error: control flow integrity check for type 'int (T::*)()' failed during non-virtual pointer to member function call
// B: note: S::f2() defined here
(t.*bitcast<T_int>(&S::f2))();
break;
case 'c':
// C: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual pointer to member function call
// C: note: vtable is of type 'S'
(s.*bitcast<S_int>(&S::g1))();
break;
case 'd':
// D: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual pointer to member function call
// D: note: vtable is of type 'T'
(reinterpret_cast<S &>(t).*&S::g2)();
break;
case 'e':
// E: runtime error: control flow integrity check for type 'void (S::*)()' failed during virtual pointer to member function call
// E: note: vtable is of type 'S'
(s.*bitcast<S_void>(&T::g3))();
break;
case 'f':
(s.*&SBase1::b1)();
break;
case 'g':
(s.*&SBase2::b2)();
break;
}
}