1 // RUN: %clangxx_cfi -o %t %s 2 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 3 4 // RUN: %clangxx_cfi -DB32 -o %t %s 5 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 6 7 // RUN: %clangxx_cfi -DB64 -o %t %s 8 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 9 10 // RUN: %clangxx_cfi -DBM -o %t %s 11 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 12 13 // RUN: %clangxx -o %t %s 14 // RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s 15 16 // Tests that the CFI enforcement also applies to virtual destructor calls made 17 // via 'delete'. 18 19 #include <stdio.h> 20 #include "utils.h" 21 22 struct A { 23 virtual ~A(); 24 }; 25 ~A()26A::~A() {} 27 28 struct B { 29 virtual ~B(); 30 }; 31 ~B()32B::~B() {} 33 main()34int main() { 35 #ifdef B32 36 break_optimization(new Deriver<B, 0>); 37 #endif 38 39 #ifdef B64 40 break_optimization(new Deriver<B, 0>); 41 break_optimization(new Deriver<B, 1>); 42 #endif 43 44 #ifdef BM 45 break_optimization(new Deriver<B, 0>); 46 break_optimization(new Deriver<B, 1>); 47 break_optimization(new Deriver<B, 2>); 48 #endif 49 50 A *a = new A; 51 break_optimization(a); 52 53 // CFI: 1 54 // NCFI: 1 55 fprintf(stderr, "1\n"); 56 57 delete (B *)a; // UB here 58 59 // CFI-NOT: 2 60 // NCFI: 2 61 fprintf(stderr, "2\n"); 62 } 63